http://hi.baidu.com/shirdrn/blog/item/1467311997a65d4343a9adf8.html
OpenGL程序框架在很多教程中都有人介绍过了,作为我个人学习,我还是写一下。
在实现OpenGL的框架之前,必须保证你已经正确配置好了OpenGL,才能通过建立OpenGL框架来测试。
启动VC 6,新建一个名称为OpenGL的Win32 Console Application,新建一些头文件和CPP文件,工程结果如图所示:
下面对工程中的文件简单介绍:
第一个:StdAfx.h头文件
StdAfx.h是与VC的框架相关,生成程序框架的。该文件内容如下所示:
// stdafx.h : include file for standard system include files, #if !defined(AFX_STDAFX_H__78441E1B_7353_4082_9B09_20806569F5EA__INCLUDED_) #if _MSC_VER > 1000 #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #include <windows.h> // Windows的头文件 #include <mmsystem.h> // TODO: reference additional headers your program requires here //{{AFX_INSERT_LOCATION}} #endif // !defined(AFX_STDAFX_H__78441E1B_7353_4082_9B09_20806569F5EA__INCLUDED_) |
这里默认主要生成工程的程序框架,而且,我们已经将OpenGL库配置到VC里面,现在它已经作为工程框架的一部分,在StdAfx.h文件中引入。
第二个:StdAfx.cpp头文件
这是个C++源文件,并没有做什么事情,只是引用了StdAfx.h头文件,代码如下所示:
// stdafx.cpp : source file that includes just the standard includes #include "stdafx.h" // TODO: reference any additional headers you need in STDAFX.H |
只是包含StdAfx.h头文件。
第三个:OpenGL.h头文件
这里,声明了一个OpenGL类,定义中声明了安装、初始化、渲染、清除OpenGL的方法,实现是在OpenGL.cpp文件中。OpenGL.h头文件的源代码如下所示:
// OpenGL.h: interface for the OpenGL class. #if !defined(AFX_OPENGL_H__17B7289C_7956_41C5_89B9_621E3C435389__INCLUDED_) #if _MSC_VER > 1000 class OpenGL HDC hDC; // GDI设备描述表 #endif // !defined(AFX_OPENGL_H__17B7289C_7956_41C5_89B9_621E3C435389__INCLUDED_) |
各个方法的功能可以参考注释。
第四个:OpenGL.cpp类文件
该类中真正实现了头文件OpenGL.h中声明的方法。源代码如下所示:
// OpenGL.cpp : Defines the entry point for the console application. // glFlush(); // 更新窗口 } |
注释已经非常清晰地解释了各个方法功能的实现及其原理。
第五个:OpenGLFramework.cpp源文件
该文件中,涉及到了VC的实现机制,即基于消息机制,可以通过参考其他更多的关于VC的内容,来了解VC。
源代码如下所示:
// OpenGLFramework.cpp : Defines the entry point for the application. #include "stdafx.h" #include "OpenGL.h" // OpenGL* m_OpenGL; HDC hDC; // GDI设备句柄,将窗口连接到 GDI( 图形设备接口) HGLRC hRC=NULL; // 渲染描述句柄,将OpenGL调用连接到设备描述表 HWND hWnd=NULL; // 保存 Windows 分配给程序的窗口句柄 int Width = 400;// 窗口宽 int Height= 300;// 窗口高 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_AWS_OVERLAPPEDWINDOWPPWINDOW|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的程序框架", dwStyle|WS_CLIPCHILDREN|WS_CLIPSIBLINGS, nX, nY,Width, Height, NULL,NULL,hInst,NULL); // 创建窗口 ShowWindow( hWnd, SW_SHOWDEFAULT ); // 显示窗口 UpdateWindow( hWnd ); // 刷新窗口 GameLoop(); // 进入消息循环 return 0; } |
可以参考注释来简单了解一下。
测试OpenGL程序框架
现在可以测试,显示OpenGL程序框架了。而且,在以后的所有OpenGL应用,都可以基于该程序框架来开发。
测试如图所示:
实际上,这个框架就是一个自定义的窗口。