【OpenGL相关】用高版本visual studio打开老版本的OpenGL工程文件可能会遇到的问题

4 篇文章 0 订阅
2 篇文章 0 订阅


在3D图形程序设计课程进行学习的过程中,老师为我们提供了一些课本上的工程案例,但是这些工程案例过于老旧(创建时间甚至有05年的),使用的工程也是vs2010这些比较老的版本。
本人使用的是VS2022,虽然可以自动升级项目,但是因为代码结构过于老旧,所以需要对项目进行一些设置修改才能正常编译运行,包括——修改字符集、无法解析的外部符号……这里先放出测试代码,具体修改方法见下文

OpenGL库资源

OpenGL开发库(包括鼠标滚轮事件的扩展库),直接下载即可
资源下载

测试代码

OpenGL.h

// OpenGL.h: interface for the OpenGL class.
//
//

#if !defined(AFX_OPENGL_H__17B7289C_7956_41C5_89B9_621E3C435389__INCLUDED_)
#define AFX_OPENGL_H__17B7289C_7956_41C5_89B9_621E3C435389__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

class OpenGL  
{	public:	OpenGL();
	virtual ~OpenGL();
	public:

	HDC		hDC;			// GDI设备描述表
	HGLRC	hRC;		// 永久着色描述表
	BOOL	SetupPixelFormat(HDC hDC);
	void	init(int Width, int Height);
	void	Render();
	void	CleanUp();
};

#endif // !defined(AFX_OPENGL_H__17B7289C_7956_41C5_89B9_621E3C435389__INCLUDED_)

OpenGL.cpp

// OpenGL.cpp: implementation of the OpenGL class.
//程序设计:唐明理	2005.2
//E_mail cqtml@163.com
//
#include "stdafx.h"
#include "OpenGL.h"
//
#include "stdafx.h"
#include "OpenGL.h"
//
extern HWND	hWnd;

//
OpenGL::OpenGL()
{
}
OpenGL::~OpenGL()
{	CleanUp();
}
BOOL OpenGL::SetupPixelFormat(HDC hDC0)//检测安装OpenGL
{	int nPixelFormat;					  // 象素点格式
	hDC=hDC0;
	PIXELFORMATDESCRIPTOR pfd = { 
	    sizeof(PIXELFORMATDESCRIPTOR),    // pfd结构的大小 
	    1,                                // 版本号 
	    PFD_DRAW_TO_WINDOW |              // 支持在窗口中绘图 
	    PFD_SUPPORT_OPENGL |              // 支持 OpenGL 
	    PFD_DOUBLEBUFFER,                 // 双缓存模式 
	    PFD_TYPE_RGBA,                    // RGBA 颜色模式 
	    16,                               // 24 位颜色深度 
	    0, 0, 0, 0, 0, 0,                 // 忽略颜色位 
	    0,                                // 没有非透明度缓存 
	    0,                                // 忽略移位位 
	    0,                                // 无累加缓存 
	    0, 0, 0, 0,                       // 忽略累加位 
	    16,                               // 32 位深度缓存     
	    0,                                // 无模板缓存 
	    0,                                // 无辅助缓存 
	    PFD_MAIN_PLANE,                   // 主层 
	    0,                                // 保留 
	    0, 0, 0                           // 忽略层,可见性和损毁掩模 
	}; 
	if (!(nPixelFormat = ChoosePixelFormat(hDC, &pfd)))
		{ MessageBox(NULL,"没找到合适的显示模式","Error",MB_OK|MB_ICONEXCLAMATION);
	      return FALSE;
		}
	SetPixelFormat(hDC,nPixelFormat,&pfd);//设置当前设备的像素点格式
	hRC = wglCreateContext(hDC);          //获取渲染描述句柄
	wglMakeCurrent(hDC, hRC);             //激活渲染描述句柄
	return TRUE;
}
void OpenGL::init(int Width, int Height)
{	glViewport(0,0,Width,Height);			// 设置OpenGL视口大小。	
	glMatrixMode(GL_PROJECTION);			// 设置当前矩阵为投影矩阵。
	glLoadIdentity();						// 重置当前指定的矩阵为单位矩阵
	gluPerspective							// 设置透视图
		( 54.0f,							// 透视角设置为 45 度
		  (GLfloat)Width/(GLfloat)Height,	// 窗口的宽与高比
		  0.1f,								// 视野透视深度:近点1.0f
		  3000.0f							// 视野透视深度:始点0.1f远点1000.0f
		);
	// 这和照象机很类似,第一个参数设置镜头广角度,第二个参数是长宽比,后面是远近剪切。
	glMatrixMode(GL_MODELVIEW);				// 设置当前矩阵为模型视图矩阵
	glLoadIdentity();						// 重置当前指定的矩阵为单位矩阵
//====================================================
}
void OpenGL::Render()//OpenGL图形处理
{	glClearColor(0.0f, 0.0f, 0.3f, 1.0f);			 // 设置刷新背景色
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);// 刷新背景
	glLoadIdentity();								 // 重置当前的模型观察矩阵

	glFlush();										 // 更新窗口
	SwapBuffers(hDC);								 // 切换缓冲区
}
void OpenGL::CleanUp()//清除OpenGL
{
	 wglMakeCurrent(hDC, NULL);                       //清除OpenGL
	 wglDeleteContext(hRC);                           //清除OpenGL

}

StdAfx.h

// stdafx.h : include file for standard system include files,
//  or project specific include files that are used frequently, but
//      are changed infrequently
//

#if !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_)
#define AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers

#include <windows.h>	// Windows的头文件

#include <mmsystem.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <assert.h>
#include <gl\gl.h>		// OpenGL32库的头文件
#include <gl\glu.h>		// GLu32库的头文件
#include <gl\glaux.h>	// GLaux库的头文件
#pragma comment( lib, "winmm.lib")
#pragma comment( lib, "opengl32.lib")	// OpenGL32连接库
#pragma comment( lib, "glu32.lib")		// GLu32连接库
#pragma comment( lib, "glaux.lib")		// GLaux连接库
// TODO: reference additional headers your program requires here

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_)

StdAfx.cpp

// stdafx.cpp : source file that includes just the standard includes
//	OpenGL的程序框架.pch will be the pre-compiled header
//	stdafx.obj will contain the pre-compiled type information

#include "stdafx.h"

// TODO: reference any additional headers you need in STDAFX.H
// and not in this file

OpenGL的程序框架.cpp

// OpenGL的程序框架.cpp : Defines the entry point for the application.
//程序设计:唐明理	2005.2
//E_mail cqtml@163.com
#include "stdafx.h"
#include "OpenGL.h"
//
OpenGL* m_OpenGL;
HDC		hDC;		// GDI设备句柄,将窗口连接到 GDI( 图形设备接口)
HGLRC	hRC=NULL;	// 渲染描述句柄,将OpenGL调用连接到设备描述表 
HWND	hWnd=NULL;	// 保存 Windows 分配给程序的窗口句柄
int		Width = 800;// 窗口宽
int		Height= 600;// 窗口高
int		bits  = 16;	// 颜色深度
void GameLoop()
{   MSG msg; 
    BOOL fMessage;
    PeekMessage(&msg, NULL, 0U, 0U, PM_NOREMOVE);
    while(msg.message != WM_QUIT)	// 消息循环
    {   fMessage = PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE);
        if(fMessage)				//有消息
			{ TranslateMessage(&msg);
              DispatchMessage(&msg);
			}
        else  m_OpenGL->Render();	//无消息
    }
}
LRESULT WINAPI MsgProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam )// 消息处理
{	switch(message)
	{	case WM_CREATE:						// 建立窗口
			hDC = GetDC(hWnd);				// 获取当前窗口的设备句柄
			m_OpenGL->SetupPixelFormat(hDC);// 调用显示模式安装功能
			return 0;		break;
		case WM_CLOSE:						// 关闭窗口
			m_OpenGL->CleanUp();			// 结束处理
			PostQuitMessage(0);
			return 0;		break;
		case WM_SIZE:						// 窗口尺寸变化
			Height = HIWORD(lParam);		// 窗口的高
			Width  = LOWORD(lParam);		// 窗口的宽
			if (Height==0)	Height=1;		// 防止被0 除
			m_OpenGL->init(Width,Height);
			return 0;		break;
		case WM_DESTROY:					// 退出消息
            PostQuitMessage(0);
            return 0;		break;
        case WM_KEYUP:						// 按ESC退出,全屏模式必需要加入的退出方式。
            switch (wParam)
            { case VK_ESCAPE:
					m_OpenGL->CleanUp();	// 结束处理
				    PostQuitMessage(0);
				    return 0;break;
            } 
		default:			break;
	}
	return (DefWindowProc(hWnd, message, wParam, lParam));
}
INT WINAPI WinMain(HINSTANCE hInst,HINSTANCE,LPSTR,INT )// WinMain程序入口
{   // 注册窗口类
	bool fullScreen =TRUE;
	DWORD	dwExStyle;		// Window 扩展风格
	DWORD	dwStyle;		// Window 窗口风格
	RECT	windowRect;		// 窗口尺寸
	int		nX=0,nY=0;
/*	if (MessageBox(NULL,"使用全屏模式吗?", "将进入OpenGL,选择显示模式",
		           MB_YESNO|MB_ICONQUESTION|MB_SYSTEMMODAL)==IDNO)
		{fullScreen =false;}			// 选择窗口模式
	if (fullScreen)						// 选择全屏模式
	{	DEVMODE dmScr;					// 设备模式
		memset(&dmScr,0,sizeof(dmScr));	// 确保内存分配
		dmScr.dmSize=sizeof(dmScr);		// Devmode 结构的大小
		dmScr.dmPelsWidth = Width;		// 屏幕宽
		dmScr.dmPelsHeight= Height;		// 屏幕高
		dmScr.dmBitsPerPel= 16;			// 色彩深度
		dmScr.dmDisplayFrequency=75;	// 刷屏速度
		dmScr.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT|DM_DISPLAYFREQUENCY;
		if (ChangeDisplaySettings(&dmScr, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
			{fullScreen=FALSE;}
		dwExStyle=WS_EX_APPWINDOW;		// Window 扩展风格
		dwStyle=WS_POPUP;				// Window 窗口风格
		ShowCursor(FALSE);				// 隐藏鼠标
	}
	else*/
	{	dwExStyle=WS_EX_APPWINDOW|WS_EX_WINDOWEDGE;	// 使窗口具有3D外观
		dwStyle=WS_OVERLAPPEDWINDOW;				// 使用标准窗口
		//WS_OVERLAPPEDWINDOW是有标题栏,窗口菜单,最大、小化按钮和可调整尺寸的窗口
		int wid=GetSystemMetrics(SM_CXSCREEN);		// 获取当前屏幕宽
		int hei=GetSystemMetrics(SM_CYSCREEN);		// 获取当前屏幕高
		nX=(wid-Width)/2;nY=(hei-Height)/2;			// 计算窗口居中用
	}
//-------------------------------------------------------------------
	AdjustWindowRectEx(&windowRect,dwStyle,FALSE,dwExStyle);
									//根据窗口风格来调整窗口尺寸达到要求的大小
	char cc[]="tml";
    WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L, 
                      GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
                      cc, NULL };
    RegisterClassEx( &wc );
	m_OpenGL=new OpenGL();//
	hWnd = CreateWindowEx(NULL,cc,"学OpenGL编3D游戏 [ 1.OpenGL的程序框架 ])",
						  dwStyle|WS_CLIPCHILDREN|WS_CLIPSIBLINGS,
						  nX, nY,Width, Height,
						  NULL,NULL,hInst,NULL);	// 创建窗口
	ShowWindow( hWnd, SW_SHOWDEFAULT );				// 显示窗口
	UpdateWindow( hWnd );							// 刷新窗口
	GameLoop();										// 进入消息循环
    return 0;
}

操作流程

在正确配置好OpenGL开发环境的前提下,在VS2022新建一个桌面应用程序,可以为我们省去在项目设置中把控制台转为窗口的步骤(如果创建的是空项目也没事,之后会教你修改)
新建窗口文件可以为我们省去把控制台转为窗口的步骤
如果你已经有文件了,可以用“导入现有项”导入这五个文件,不然就根据上面的测试代码新建对应的.cpp 和 .h文件

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这里就遇到了我们第一个错误,这个错误是因为框架过老(05年的),当时字符集还没用上unicode(现在的字符集默认都是Unicode)。

解决方法

随便点一下某一行代码,打开项目->(项目名)属性
在这里插入图片描述
转到配置属性-高级 的“字符集”,改成“使用多字节字符型”

在这里插入图片描述在这里插入图片描述一路确定,发现问题解决了
在这里插入图片描述
编译运行,结果如下
在这里插入图片描述
如果你创建的项目是空项目,就需要额外修改一些内容,因为建空项目时默认为控制台,将工程属性改为_WINDOWS即可

还是来到项目设置,选择 链接器-系统-子系统,将控制台修改为窗口
在这里插入图片描述在这里插入图片描述
在C/C++ -预处理器-预处理器定义,将CONSOLE修改为WINDOWS

在这里插入图片描述在这里插入图片描述

更多的问题

我在编写上面内容之后,又遇到了一些新的问题
在这里插入图片描述注意看冲突的类型文件,是glaux.lib和glu32.lib
此时需要到
VS安装目录\20xx(根据你的visual studio版本而定)\Community\VC\Tools\MSVC\14.32.31326(不一定是这个,根据你的版本号而定)\lib\x64文件夹内 检查一下是否有这几个库文件
在这里插入图片描述复制这两个文件,返回上一级,进入x86文件夹,把这几个库文件复制进去(我配置库文件的时候在x64和x86都放了)
在这里插入图片描述回到visual studio,把上方工具栏的X64改成X86
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

此时需要重新打开项目属性,按照之前提到的解决方法重新设置一遍
在这里插入图片描述在这里插入图片描述在这里插入图片描述要着重检查运行库是不是X86,不是的话需要手动修改一下
在这里插入图片描述
一路确定,编译运行,成功解决问题
在这里插入图片描述

2022/10/21补充

glaux.lib(tk.obj) : error LNK2019: 无法解析的外部符号 _sscanf,该符号在函数 _GetRegistrySysColors@8 中被引用的解决方法:
在 项目属性->链接器->输入->附加依赖项中添加依赖项 legacy_stdio_definitions.lib;
在这里插入图片描述在这里插入图片描述

参考文章

参考文章
[1]“char*”类型的值不能用于初始化“LPTSTR”类型的实体报错及改正
[2]error LNK2019: 无法解析的外部符号 _main,函数 “int __cdecl invoke_main(void)“ (?invoke_main@@YAHXZ) 中引用了该符号

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值