【OpenGL】VS2005下创建基于Win32项目的OpenGL窗口
2012-09-23 17:53
423 查看
(2010-03-08)
目前很多关于OpenGL的教材或教程都是基于VC来创建Win32下的OpenGL窗口的,而VS2005下的Win32项目的自生成代码与VC的还是略有不同。为了方便以后在VS2005下开发OpenGL程序,保留一个创建OpenGL窗口的模板是必要的。
假设新建了一个名为glTemp的Win32项目,找到其主函数(即程序入口点)所在的文件glTemp.cpp,在其中编写创建OpenGL窗口的代码:
(1)首先不要忘了在stdafx.h中加入OpenGL必要的头文件和链接库:
#include <gl/gl.h>
#include <gl/glu.h>
#include <gl/glaux.h>
#include <gl/glut.h>
#pragma comment(lib,"opengl32.lib")
#pragma comment(lib,"glu32.lib")
#pragma comment(lib,"glaux.lib")
#pragma comment(lib,"glut32.lib")
当然,.lib库文件也可以用非编程方式,而通过设置VS2005项目属性加入。
(2)glTemp.cpp代码如下:
目前很多关于OpenGL的教材或教程都是基于VC来创建Win32下的OpenGL窗口的,而VS2005下的Win32项目的自生成代码与VC的还是略有不同。为了方便以后在VS2005下开发OpenGL程序,保留一个创建OpenGL窗口的模板是必要的。
假设新建了一个名为glTemp的Win32项目,找到其主函数(即程序入口点)所在的文件glTemp.cpp,在其中编写创建OpenGL窗口的代码:
(1)首先不要忘了在stdafx.h中加入OpenGL必要的头文件和链接库:
#include <gl/gl.h>
#include <gl/glu.h>
#include <gl/glaux.h>
#include <gl/glut.h>
#pragma comment(lib,"opengl32.lib")
#pragma comment(lib,"glu32.lib")
#pragma comment(lib,"glaux.lib")
#pragma comment(lib,"glut32.lib")
当然,.lib库文件也可以用非编程方式,而通过设置VS2005项目属性加入。
(2)glTemp.cpp代码如下:
// glTemp.cpp : 定义应用程序的入口点。 // #include "stdafx.h" #include "glTemp.h" #define MAX_LOADSTRING 100 // 全局变量: HINSTANCE hInst; // 当前实例 TCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本 TCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口类名 // 此代码模块中包含的函数的前向声明: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); HWND hWnd; //窗口句柄 HDC hDC; //私有的GDI设备描述表 HGLRC hRC=NULL; //着色描述表 RECT rect; int sw=640,sh=480; //全屏分辨率 bool fullscreen=1; //全屏标志 GLfloat aspect; //斜率 bool keys[256]; //按键是否被按下的信息 int mx,my; //获取鼠标指针坐标 //判断鼠标是否移动、是否左击、右击、双击 bool m_move,m_left,m_right,m_dclick; //初始化OpenGL窗口 void SceneInit(int w,int h) { glShadeModel(GL_SMOOTH); //允许平滑着色 glClearColor(0.6f,0.2f,0.0f,0.5); //设置背景色 glClearDepth(1.0f); //设置深度缓冲区 glEnable(GL_DEPTH_TEST); //允许深度测试 glDepthFunc(GL_LEQUAL); //深度测试的类型 glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST); //更加精细的透视校正 } //重置OpenGL场景尺寸 void SceneResizeViewport(GLsizei w,GLsizei h) { if(h==0) h=1; aspect=(GLfloat)w/(GLfloat)h; glViewport(0,0,w,h); //设置当前视口 glMatrixMode(GL_PROJECTION); //选择投影矩阵 glLoadIdentity(); //重置投影矩阵 gluPerspective(45.0f,aspect,0.1f,100.0f); //设置透视视景 glMatrixMode(GL_MODELVIEW); //选择模型视图矩阵 glLoadIdentity(); //重置模型视图矩阵 } //所有OpenGL绘制 void SceneShow(GLvoid) { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); //清屏和清除深度缓冲区 glLoadIdentity(); //重置当前Modelview矩阵(原点回到窗口中心) gluLookAt(0,0,10,0,0,0,0,1,0);//设置视觉坐标系(视点位置,目标点位置,视点向上方向) /*添加任何绘图代码*/ } //激活OpenGL void EnbleOpenGL() { PIXELFORMATDESCRIPTOR pfd; //像素格式描述符 int iFormat; hDC=GetDC(hWnd); //获取设备描述表 ZeroMemory(&pfd,sizeof(pfd)); pfd.nSize=sizeof(pfd); //格式描述符大小 pfd.nVersion=1; //版本号 //格式必须支持窗口、OpenGL、双缓冲 pfd.dwFlags=PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER; pfd.iPixelType=PFD_TYPE_RGBA; //申请RGBA格式 pfd.cColorBits=16; //色彩深度 pfd.cDepthBits=16; //深度缓存(Z缓存) pfd.iLayerType=PFD_MAIN_PLANE; //主绘图层 iFormat=ChoosePixelFormat(hDC,&pfd); //选择像素格式 SetPixelFormat(hDC,iFormat,&pfd); //设置像素格式 hRC=wglCreateContext(hDC); //取得着色描述表 wglMakeCurrent(hDC,hRC); //激活着色描述表 } //关闭OpenGL void DisableOpenGL() { wglMakeCurrent(NULL,NULL); //释放DC和RC描述表 wglDeleteContext(hRC); //删除RC ReleaseDC(hWnd,hDC); //释放DC } //改变屏幕分辨率 bool ChangeResolution(int w,int h,int bitdepth) { DEVMODE devMode; //设备模式 int modeSwitch; int closeMode=0; EnumDisplaySettings(NULL,closeMode,&devMode); devMode.dmBitsPerPel=bitdepth; //每像素所选的色彩深度 devMode.dmPelsWidth=w; //屏幕宽 devMode.dmPelsHeight=h; //屏幕高 devMode.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT; //设置显示模式 modeSwitch=ChangeDisplaySettings(&devMode,CDS_FULLSCREEN); if(modeSwitch==DISP_CHANGE_SUCCESSFUL) return true; else { ChangeDisplaySettings(NULL,0); return false; } } //主函数(程序入口) int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); // TODO: 在此放置代码。 MSG msg; HACCEL hAccelTable; bool bQuit=false; m_move=false;m_left=false;m_right=false;m_dclick=false; if(MessageBox(NULL,L"是否选择全屏显示模式?",L"全屏方式运行?",MB_YESNO|MB_ICONQUESTION)==IDNO) fullscreen=0; // 初始化全局字符串 LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadString(hInstance, IDC_GLTEMP, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); // 执行应用程序初始化: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_GLTEMP)); // 主消息循环: while(!bQuit) { if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) if(msg.message==WM_QUIT) //收到退出消息 bQuit=true; else { TranslateMessage(&msg); //翻译消息 DispatchMessage(&msg); //发送消息 } else { //OpenGL动画 SceneShow(); SwapBuffers(hDC); //交换缓存 /*添加响应键盘或鼠标消息的代码*/ } } //销毁OpenGL窗口的几个后续操作 DisableOpenGL(); ShowWindow(hWnd,SW_HIDE); DestroyWindow(hWnd); ChangeDisplaySettings(NULL,0); return (int) msg.wParam; } // // 函数: MyRegisterClass() // // 目的: 注册窗口类。 // // 注释: // // 仅当希望 // 此代码与添加到 Windows 95 中的“RegisterClassEx” // 函数之前的 Win32 系统兼容时,才需要此函数及其用法。调用此函数十分重要, // 这样应用程序就可以获得关联的 // “格式正确的”小图标。 // ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex; //窗口类结构 wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_OWNDC; //为窗口取得DC wcex.lpfnWndProc = WndProc; //WndProc处理消息 wcex.cbClsExtra = 0; //无额外窗口数据 wcex.cbWndExtra = 0; //无额外窗口数据 wcex.hInstance = hInstance; //设置实例 wcex.hIcon = LoadIcon(NULL,IDI_APPLICATION); //装入缺省图标 wcex.hCursor = LoadCursor(NULL, IDC_ARROW); //装入鼠标指针 wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); //背景 wcex.lpszMenuName = MAKEINTRESOURCE(IDC_GLTEMP); //菜单 wcex.lpszClassName = L"Name"; //类名 wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); //注册窗口类 return RegisterClassEx(&wcex); } // // 函数: InitInstance(HINSTANCE, int) // // 目的: 保存实例句柄并创建主窗口 // // 注释: // // 在此函数中,我们在全局变量中保存实例句柄并 // 创建和显示主程序窗口。 // BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { hInst = hInstance; // 将实例句柄存储在全局变量中 if(fullscreen) { ChangeResolution(640,480,16); hWnd=CreateWindow(L"Name",L"Lesson1",WS_POPUP|WS_CLIPSIBLINGS|WS_VISIBLE,0,0,GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN),NULL,NULL,hInstance,NULL); } else { hWnd=CreateWindow(L"Name",L"Lesson1",WS_TILEDWINDOW|WS_VISIBLE, GetSystemMetrics(SM_CXSCREEN)/2-sw/2, GetSystemMetrics(SM_CYSCREEN)/2-sh/2, sw,sh,NULL,NULL,hInstance,NULL); ChangeDisplaySettings(NULL,0); } //OpenGL窗口创建完毕的后续工作 ShowWindow(hWnd,nCmdShow); UpdateWindow(hWnd); EnbleOpenGL(); SceneInit(sw,sh); if(!fullscreen) { GetWindowRect(hWnd,&rect); sw=rect.right-rect.left; sh=rect.bottom-rect.top; if(sw>0&&sh>0) SceneResizeViewport(sw,sh); } else { SceneResizeViewport(GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN)); } return TRUE; } // // 函数: WndProc(HWND, UINT, WPARAM, LPARAM) // // 目的: 处理主窗口的消息。 // // WM_COMMAND - 处理应用程序菜单 // WM_PAINT - 绘制主窗口 // WM_DESTROY - 发送退出消息并返回 // // LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; switch (message) { case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // 分析菜单选择: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // TODO: 在此添加任意绘图代码... EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); break; case WM_CREATE: GetWindowRect(hWnd,&rect); sw=rect.right-rect.left; sh=rect.bottom-rect.top; SceneResizeViewport(sw,sh); break; case WM_SIZE: if(!fullscreen) { GetWindowRect(hWnd,&rect); sw=rect.right-rect.left; sh=rect.bottom-rect.top; if(sw>0&&sh>0) SceneResizeViewport(sw,sh); } else { SceneResizeViewport(GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN)); } break; case WM_CLOSE: ShowWindow(hWnd,SW_HIDE); PostQuitMessage(0); break; case WM_KEYDOWN: keys[wParam]=true; switch(wParam) { case VK_ESCAPE: PostMessage(hWnd,WM_CLOSE,0,0); break; case VK_F1: { hInst=GetModuleHandle(NULL); break; } } break; case WM_KEYUP: keys[wParam]=false; break; //lParam的低4位为鼠标指针的x坐标,高4位为y坐标 case WM_LBUTTONDOWN: // 处理鼠标左键按下消息 { mx=LOWORD(lParam); my=HIWORD(lParam); m_left=true; break; } case WM_LBUTTONUP: // 处理鼠标左键抬起消息 { mx=LOWORD(lParam); my=HIWORD(lParam); m_left=false; break; } case WM_RBUTTONDOWN: // 处理鼠标右键按下消息 { mx=LOWORD(lParam); my=HIWORD(lParam); m_right=true; break; } case WM_RBUTTONUP: // 处理鼠标右键抬起消息 { mx=LOWORD(lParam); my=HIWORD(lParam); m_right=false; break; } case WM_LBUTTONDBLCLK: // 处理鼠标左键双击消息 { mx=LOWORD(lParam); my=HIWORD(lParam); m_dclick=true; break; } case WM_MOUSEMOVE: // 处理鼠标移动消息 { mx=LOWORD(lParam); my=HIWORD(lParam); m_move=true; break; } default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } // “关于”框的消息处理程序。 INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { UNREFERENCED_PARAMETER(lParam); switch (message) { case WM_INITDIALOG: return (INT_PTR)TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); return (INT_PTR)TRUE; } break; } return (INT_PTR)FALSE; }
相关文章推荐
- VS2005创建win32 dll的项目向导
- Python使用Windows API创建窗口示例【基于win32gui模块】
- vs2005 智能设备 win32 创建项目失败
- VS2005创建win32 dll的项目向导
- Nehe OpenGL教程第一课-创建一个OpenGL窗口(Win32)
- OpenGL1-创建窗口(建立Win32的OpenGL开发环境 )(代码上传)
- 基于Win32的VTK多窗口程序创建
- OpenGL1-创建窗口(建立Win32的OpenGL开发环境 )(代码上传)
- VS2005创建win32 dll的项目向导
- VS2005创建win32 dll的项目向导
- MOOC清华《VC++面向对象与可视化程序设计》第1章:空白窗口的创建(Win32项目)
- 基于SDK的Win32窗口创建
- 用多线程方法实现在MFC/WIN32中调用OpenGL函数并创建OpenGL窗口
- Win32汇编:创建简单的窗口
- win32常用的消息WM_CREATE - 窗口创建成功,但还未显示之前
- 【VC编程】笔记1--创建一个Win32的应用程序,并显示创建的窗口和菜单
- 初触cocos2d-x,win32平台搭建以及创建第一个cocos2d-x项目遇到问题总结
- 基于Win32框架的OpenGL程序
- vs2005如何打开vs2008中创建的工程(项目)【转】
- 用vs2008和vs2005创建win32 console application