一个面向对象的OPENGL程序框架

原文:http://blog.csdn.net/lingang_/article/details/3347463


最近在看徐明亮的<>,发觉这本书在国人的著作中尚属不错,在此先要感谢作者。

这个框摘自<>,我修改了部分代码,使之能在VS2005中顺利运行。

代码清单:

  1. //========================================================
  2. /**
  3. *  @file  GLWindows.h
  4. *
  5. *  项目描述: OpenGL程序框架演示
  6. *  文件描述:  程序窗口类  
  7. *  适用平台: Windows98/2000/NT/XP
  8. *  
  9. *
  10. */     
  11. //========================================================
  12. #ifndef __GLWINDOW_H__
  13. #define __GLWINDOW_H__

  14. #include                                              /**< 包含windows.h头文件 */

  15. #pragma warning(disable: 4311)                                  /**< 禁止编译器出现类型转换的警告 */
  16. #pragma warning(disable: 4312)
  17. #pragma warning(disable: 4244)

  18. /** windows窗口类 */
  19. class GLWindow                                                          
  20. {
  21. public:
  22. /** 重要的窗口函数  */
  23.     
  24.     /** 构造函数 */
  25.     GLWindow();
  26.     /** 创建windows窗口 */
  27.     bool    Create(const char * window_title, const char * class_name, bool fullscreen,HINSTANCE h_instance, LPVOID lpParam);
  28.     /** 删除OpenGL窗口 */
  29.     void    Destroy();
  30.     /** 改变窗口的显示设置 */
  31.     bool    ChangeScreenSetting();
  32.     /** 当窗口大小改变时,通知OpenGL调整大小 */
  33.     void    ReshapeGL();
  34.     /** Swap Buffers (Double Buffering) */
  35.     void    SwapBuffers() { ::SwapBuffers(m_hDC); }

  36. /** 下面函数为设置/返回窗口类的属性 */
  37.     
  38.     /** 设置窗口左上角的位置 */
  39.     void    SetPosX(int x);
  40.     void    SetPosX(unsigned short x) { SetPosX((signed short)x); }     
  41.     void    SetPosY(int y);
  42.     void    SetPosY(unsigned short y) { SetPosY((signed short)y); }     
  43.     /** 返回窗口的大小 */
  44.     int     GetWidth();
  45.     int     GetHeight();
  46.     /** 设置窗口的大小 */
  47.     void    SetWidth(int width);
  48.     void    SetHeight(int height);
  49.     /** 返回窗口左上角的位置 */
  50.     int     GetPosX();
  51.     int     GetPosY();
  52.     /** 设置窗口的颜色位深 */
  53.     void    SetHiColor()    { m_BitsPerPixel = 16; }
  54.     void    SetTrueColor()  { m_BitsPerPixel = 32; }
  55.     //void  SetFullScreen(bool mode)    { m_IsFullScreen = mode; }
  56.     //bool  GetFullScreen() { return m_IsFullScreen; }
  57.     /** 重载运算符,可以让GL_Window m_Window声明后的m_Window作为窗口句柄使用 */
  58.     operator HWND() { return m_hWnd; }

  59. private:
  60.     HWND    m_hWnd;                                                     /**< 窗口句柄 */
  61.     HDC     m_hDC;                                                      /**< 设备描述表 */
  62.     HGLRC   m_hRC;                                                      /**< OpenGL渲染描述表 */

  63.     int     m_WindowPosX;                                               /**< 窗口的左上角的X位置 */
  64.     int     m_WindowPosY;                                               /**< 窗口的左上角的Y位置 */
  65.     int     m_WindowWidth;                                              /**< 窗口的宽度 */
  66.     int     m_WindowHeight;                                             /**< 窗口的高度 */
  67.     int     m_ScreenWidth;                                              /**< 全屏的宽度 */
  68.     int     m_ScreenHeight;                                             /**< 全屏的高度 */
  69.     int     m_BitsPerPixel;                                             /**< 颜色位深 */
  70.     bool    m_IsFullScreen;                                             /**< 是否全屏 */
  71. };

  72. #endif  // __GLWINDOW_H__
  1. //========================================================
  2. /**
  3. *  @file  GLWindows.h
  4. *
  5. *  项目描述: OpenGL程序框架演示
  6. *  文件描述:  程序窗口类 
  7. *  适用平台: Windows98/2000/NT/XP
  8. *  
  9. *
  10. */     
  11. //========================================================
  12. #include "GLWindow.h"                                                   /**< 包含GLwindows.h头文件 */

  13. #include                                                       /**< 包含OpenGL头文件 */
  14. #include                                                      


  15. /** 构造函数 */
  16. GLWindow::GLWindow()                                                    
  17. {
  18.     m_WindowPosX    = 0;                                                /**< 窗口的左上角的X位置 */
  19.     m_WindowPosY    = 0;                                                /**< 窗口的左上角的Y位置 */
  20.     m_WindowWidth   = 640;                                              /**< 窗口的宽度 */
  21.     m_WindowHeight  = 480;                                              /**< 窗口的高度 */
  22.     m_ScreenWidth   = 1024;                                             /**< 全屏的宽度 */
  23.     m_ScreenHeight  = 768;                                              /**< 全屏的高度 */
  24.     m_BitsPerPixel  = 16;                                               /**< 颜色位深 */
  25.     m_IsFullScreen  = false;                                            /**< 不使用全屏 */

  26.     m_hWnd = 0;
  27.     m_hDC = 0;
  28.     m_hRC = 0;
  29. }

  30. /** 返回窗口的大小 */
  31. int GLWindow::GetWidth()
  32. {
  33.     if (m_IsFullScreen == true)
  34.     {
  35.         return m_ScreenWidth;
  36.     }
  37.     else
  38.     {
  39.         return m_WindowWidth;
  40.     }
  41. }
  42. int GLWindow::GetHeight()
  43. {
  44.     if (m_IsFullScreen == true)
  45.     {
  46.         return m_ScreenHeight;
  47.     }
  48.     else
  49.     {
  50.         return m_WindowHeight;
  51.     }
  52. }

  53. /** 设置窗口的大小 */
  54. void GLWindow::SetWidth(int width)
  55. {
  56.     if (m_IsFullScreen == true)
  57.     {
  58.         m_ScreenWidth = width;
  59.     }
  60.     else
  61.     {
  62.         m_WindowWidth = width;
  63.     }
  64. }
  65. void GLWindow::SetHeight(int height)
  66. {
  67.     if (m_IsFullScreen == true)
  68.     {
  69.         m_ScreenHeight = height;
  70.     }
  71.     else
  72.     {
  73.         m_WindowHeight = height;
  74.     }
  75. }

  76. /** 返回窗口左上角的位置 */
  77. int GLWindow::GetPosX()
  78. {
  79.     if (m_IsFullScreen == false)
  80.     {
  81.         return m_WindowPosX;
  82.     }
  83.     return 0;
  84. }
  85. int GLWindow::GetPosY()
  86. {
  87.     if (m_IsFullScreen == false)
  88.     {
  89.         return m_WindowPosY;
  90.     }
  91.     return 0;
  92. }

  93. /** 设置窗口左上角的位置 */
  94. void GLWindow::SetPosX(int x)
  95. {
  96.     if (m_IsFullScreen == false)
  97.     {
  98.         m_WindowPosX = x;
  99.     }
  100. }
  101. void GLWindow::SetPosY(int y)
  102. {
  103.     if (m_IsFullScreen == false)
  104.     {
  105.         m_WindowPosY = y;
  106.     }
  107. }

  108. /** 当窗口大小改变时,通知OpenGL调整大小 */
  109. void GLWindow::ReshapeGL()
  110. {
  111.     GLsizei width = GetWidth();
  112.     GLsizei height = GetHeight();
  113.     glViewport(0, 0, width, height);                                    /**< 重新设置视口 */
  114.     glMatrixMode(GL_PROJECTION);                                    
  115.     glLoadIdentity();                                                   
  116.     gluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 1.0f, 100.0f);  
  117.     glMatrixMode(GL_MODELVIEW);                                         
  118.     glLoadIdentity();                                                   
  119. }

  120. /** 改变窗口的显示设置 */
  121. bool GLWindow::ChangeScreenSetting()
  122. {
  123.     DEVMODE dmScreenSettings;                                           /**< 设备模式 */
  124.     ZeroMemory(&dmScreenSettings, sizeof(DEVMODE));                     /**< 清零结构 */
  125.     dmScreenSettings.dmSize         = sizeof(DEVMODE);                  /**< 结构大小 */
  126.     dmScreenSettings.dmPelsWidth    = GetWidth();                       /**< 设置宽度 */
  127.     dmScreenSettings.dmPelsHeight   = GetHeight();                      /**< 设置高度 */
  128.     dmScreenSettings.dmBitsPerPel   = m_BitsPerPixel;                   /**< 设置位深度 */
  129.     //dmScreenSettings.dmDisplayFrequency = 75;                           /**< 设置屏幕刷新率 */
  130.     dmScreenSettings.dmFields       = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT ;//| DM_DISPLAYFREQUENCY;

  131.     /// 改变显示模式
  132.     if (ChangeDisplaySettings(&dmScreenSettings, 0) != DISP_CHANGE_SUCCESSFUL)
  133.     {
  134.         return false;                                                   /**< 如果失败,返回false */
  135.     }

  136.     return true;                                                        /**< 成功返回 */
  137. }

  138. /** 创建windows窗口 */
  139. bool GLWindow::Create(const char * window_title,const char * class_name,bool fullscreen, HINSTANCE h_instance, LPVOID lpParam)
  140. {
  141.     m_IsFullScreen = fullscreen;
  142.     int nX=0;
  143.     int nY=0;
  144.     PIXELFORMATDESCRIPTOR pfd =                                         /**< 设置像素描述结构 */
  145.     {
  146.         sizeof(PIXELFORMATDESCRIPTOR),                                  /**< 像素描述结构的大小 */ 
  147.         1,                                                              /**< 版本号 */
  148.         PFD_DRAW_TO_WINDOW  |                                           /**< 缓存区的输出显示在一个窗口中 */
  149.         PFD_SUPPORT_OPENGL  |                                           /**< 缓存区支持OpenGL绘图 */
  150.         PFD_STEREO          |                                           /**< 颜色缓存区是立体缓存 */
  151.         PFD_DOUBLEBUFFER,                                               /**< 颜色缓存区是双缓存 */
  152.         PFD_TYPE_RGBA,                                                  /**< 使用RGBA颜色格式 */
  153.         m_BitsPerPixel,                                                 /**< 颜色缓存区中颜色值所占的位深 */
  154.         0, 0, 0, 0, 0, 0,                                               /**< 使用默认的颜色设置 */
  155.         0,                                                              /**< 无Alpha缓存 */
  156.         0,                                                              /**< 颜色缓存区中alpha成分的移位计数 */
  157.         0,                                                              /**< 无累计缓存区 */
  158.         0, 0, 0, 0,                                                     /**< 累计缓存区无移位 */
  159.         32,                                                             /**< 32位深度缓存 */
  160.         0,                                                              /**< 无蒙版缓存 */
  161.         0,                                                              /**< 无辅助缓存区 */
  162.         PFD_MAIN_PLANE,                                                 /**< 必须为PFD_MAIN_PLANE,设置为主绘图层 */
  163.         0,                                                              /**< 表示OpenGL实现所支持的上层或下层平面的数量 */
  164.         0, 0, 0                                                         /**< 过时,已不再使用 */
  165.     };

  166.     DWORD windowStyle = WS_OVERLAPPEDWINDOW & ~WS_SIZEBOX & ~WS_MAXIMIZEBOX;    /**< 定义我们窗口类型,使用常规设定,去掉最大化按钮,并不能改变窗体大小 */
  167.     DWORD windowExtendedStyle = WS_EX_APPWINDOW;                        

  168.     if (m_IsFullScreen == true)                                         /**< 如果为全屏模式,尝试转化为全屏模式 */
  169.     {
  170.         if (ChangeScreenSetting() == false)
  171.         {                                                               /**< 全屏模式转换失败,弹出对话框提示,并尝试窗口模式 */
  172.             MessageBoxA(HWND_DESKTOP, "模式转换失败./n在窗口模式下运行.""Error", MB_OK | MB_ICONEXCLAMATION);
  173.             m_IsFullScreen = false;                                     /**< 设置为窗口模式 */
  174.         }
  175.         else                                                            /**< 如果为窗口模式 */
  176.         {
  177.             ShowCursor(false);                                          /**< 隐藏鼠标 */
  178.             windowStyle = WS_POPUP;                                     /**< 设置窗口模式为顶层窗口 */
  179.             windowExtendedStyle |= WS_EX_TOPMOST;                       
  180.         }                                                               
  181.     }

  182.     /// 调整我们窗口的大小,使其客户区的大小为我们设置的大小
  183.     RECT windowRect = {GetPosX(), GetPosY(), GetPosX() + GetWidth(), GetPosY() + GetHeight()};
  184.     if (m_IsFullScreen == false)                                        /**< 在窗口模式下使用 */
  185.     {   
  186.         windowExtendedStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;   /**< 使窗口具有3D外观 */
  187.         int wid = GetSystemMetrics(SM_CXSCREEN);        /**< 获取当前屏幕宽 */
  188.         int hei = GetSystemMetrics(SM_CYSCREEN);        /**< 获取当前屏幕高 */
  189.         nX = (wid - GetWidth()) / 2;                    /**< 计算窗口居中用 */
  190.         nY = (hei - GetHeight()) / 2;           
  191.         /// 调整我们窗口的大小,使其客户区的大小为我们设置的大小
  192.         AdjustWindowRectEx(&windowRect, windowStyle, 0, windowExtendedStyle);
  193.         /// 判断窗口的左上角是否隐藏在桌面外
  194.         if (windowRect.left < 0)                                        /**< 如果窗口X坐标为负,移动坐标到0处,并调整窗口的位置 */
  195.         {
  196.             windowRect.right -= windowRect.left;                        
  197.             windowRect.left = 0;                                        
  198.         }
  199.         if (windowRect.top < 0)                                         /**< 如果窗口Y坐标为负,移动坐标到0处,并调整窗口的位置 */
  200.         {
  201.             windowRect.bottom -= windowRect.top;                        
  202.             windowRect.top = 0;                                         
  203.         }
  204.     }

  205.     /// 创建窗口
  206.     m_hWnd = CreateWindowExA(windowExtendedStyle,                       /**< 窗口的扩展风格 */
  207.                             class_name,                                 /**< 窗口的类名 */
  208.                             window_title,                               /**< 窗口标题 */
  209.                             windowStyle,                                /**< 窗口的风格 */
  210.                             nX,nY,                                      /**< 窗口的左上角位置 */
  211.                             windowRect.right - windowRect.left,         /**< 窗口的宽度 */
  212.                             windowRect.bottom - windowRect.top,         /**< 窗口的高度 */
  213.                             HWND_DESKTOP,                               /**< 窗口的父窗口为桌面 */
  214.                             0,                                          /**< 无菜单 */
  215.                             h_instance,                                 /**< 传入窗口的实例句柄 */
  216.                             lpParam);                                   /**< 传入程序类参数 */

  217.     while (m_hWnd != 0)                                                 /**< 窗口是否创建成功 */
  218.     {
  219.         m_hDC = GetDC(m_hWnd);                                          /**< 返回窗口的设备描述表 */
  220.         if (m_hDC == 0)                                                 /**< 如果为空 */
  221.         {                                                               /**< 失败 */
  222.             break;                                                      
  223.         }

  224.         GLuint PixelFormat = ChoosePixelFormat(m_hDC, &pfd);            /**< 查找一个兼容的像素格式 */
  225.         if (PixelFormat == 0)                                           /**< 如果没找到 */
  226.         {                                                               /**< 失败 */
  227.             break;                                                      
  228.         }
  229.         if (SetPixelFormat(m_hDC, PixelFormat, &pfd) == false)          /**< 设置像素格式 */
  230.         {                                                               /**< 失败 */
  231.             break;                                                      
  232.         }
  233.         m_hRC = wglCreateContext(m_hDC);                                /**< 创建OpenGL的渲染描述表 */
  234.         if (m_hRC == 0)                                                 /**< 如果为空 */
  235.         {                                                               /**< 失败 */
  236.             break;                                                      
  237.         }
  238.         if (wglMakeCurrent(m_hDC, m_hRC) == false)                      /**< 设置当前的OpenGL的渲染对象为当前的窗口 */
  239.         {                                                               /**< 失败 */
  240.             break;                                                      
  241.         }
  242.         
  243.         ShowWindow(m_hWnd, SW_NORMAL);                                  /**< 显示窗口 */
  244.         ReshapeGL();                                                    /**< 告诉OpenGL调整窗口大小 */
  245.         return true;                                                    /**< 成功返回 */
  246.     }                                                                   

  247.     Destroy();                                                          /**< 释放资源 */
  248.     return false;                                                       /**< 返回失败 */
  249. }

  250. /** 删除OpenGL窗口 */
  251. void GLWindow::Destroy()                                    
  252. {
  253.     if (m_hWnd != 0)                                        /**< 窗口句柄是否存在 */
  254.     {
  255.         if (m_hDC != 0)                                     /**< 窗口设备描述表是否存在 */
  256.         {
  257.             wglMakeCurrent(m_hDC, 0);                       /**< 设置当前的OpenGL的渲染对象为空NULL */
  258.             if (m_hRC != 0)                                 /**< OpenGL的渲染描述表是否存在 */
  259.             {
  260.                 wglDeleteContext(m_hRC);                    /**< 释放OpenGL的渲染描述表 */
  261.                 m_hRC = 0;                                  /**< 设置OpenGL的渲染描述表为0 */
  262.             }
  263.             ReleaseDC(m_hWnd, m_hDC);                       /**< 释放窗口的设备描述表 */
  264.             m_hDC = 0;                                      /**< 设置窗口的设备描述表为0 */
  265.         }
  266.         DestroyWindow(m_hWnd);                              /**< 删除窗口 */
  267.         m_hWnd = 0;                                         /**< 设置窗口句柄为0 */
  268.     }

  269.     if (m_IsFullScreen)                                     /**< 如果为全屏模式,在程序结束后,变换到窗口模式,并显示鼠标 */
  270.     {
  271.         ChangeDisplaySettings(NULL, 0);                     /**< 变换到窗口模式 */
  272.         ShowCursor(true);                                   /**< 显示鼠标 */
  273.     }
  274. }

  1. //======================================================================
  2. /**
  3. *  @file  Framework.h
  4. *
  5. *  项目描述: OpenGL程序框架演示
  6. *  文件描述:  键盘类和程序框架类 
  7. *  适用平台: Windows98/2000/NT/XP
  8. *   
  9. *  你必须在你的继承类中完成以下函数的实现
  10. *                                                                           
  11. *  GLApplication * GLApplication::Create(const char * class_name)       
  12. *       创建你的子类的一个实例     
  13. *                                                                           
  14. *  bool Init();                                                     
  15. *       执行所有的初始化工作,如果成功函数返回true                         
  16. *                                                                           
  17. *  void Uninit();                                                   
  18. *       执行所有的卸载工作                                       
  19. *                                                                           
  20. *  void Update(DWORD milliseconds);                                     
  21. *       执行所有的更新操作,传入的参数为两次操作经过的时间,以毫秒为单位
  22. *                                                                           
  23. *  void Draw();                                                         
  24. *       执行所有的绘制操作
  25. */                                                                          
  26. //======================================================================
  27. #ifndef __GLFRAME_H__
  28. #define __GLFRAME_H__


  29. #include "GLWindow.h"                                           /**< 包含GLWindow.h头文件 */

  30. /** 定义键盘类 */
  31. class Keys                                                       
  32. {
  33. public:
  34.     /** 构造函数 */
  35.     Keys() { Clear(); }
  36.     /** 清空所有的按键信息 */
  37.     void Clear() { ZeroMemory(&m_KeyDown, sizeof(m_KeyDown)); }
  38.     /** 判断某个键是否按下 */
  39.     bool IsPressed(unsigned int key)    { return (key < MAX_KEYS) ? (m_KeyDown[key] == true) : false; }
  40.     /** 设置某个键被按下 */
  41.     void SetPressed(unsigned int key)   { if (key < MAX_KEYS) m_KeyDown[key] = true; }
  42.     /** 设置某个键被释放 */
  43.     void SetReleased(unsigned int key)  { if (key < MAX_KEYS) m_KeyDown[key] = false; }

  44. private:
  45.     static const unsigned int MAX_KEYS = 256;
  46.     bool m_KeyDown[MAX_KEYS];                                   /**< 保存256个按键的状态 */
  47. };


  48. /** 基本的程序类,继承它用来创建OpenGL程序 */
  49. class GLApplication                                         
  50. {
  51. public:
  52.     /** 创建一个全局的Create函数,这个函数必须被继承类实现 */
  53.     static GLApplication * Create(const char * class_name); /**< 创建你自己的子类 */

  54.     /** 虚析构函数 */
  55.     virtual ~GLApplication() {};

  56. protected:
  57.     /** 下面的函数必须被继承类实现,完成基本的OpenGL渲染过程 */
  58.     virtual bool    Init() = 0;                         /**< OpenGL的初始化 */ 
  59.     virtual void    Uninit() = 0;                           /**< OpenGL的卸载 */
  60.     virtual void    Update(DWORD milliseconds) = 0;             /**< 执行OpenGL程序的更新 */
  61.     virtual void    Draw() = 0;                                 /**< 绘制OpenGL场景 */

  62.     /** 通用的函数 */
  63.     void    ToggleFullscreen();                                 /**< 切换 全屏/窗口模式 */
  64.     void    TerminateApplication();                             /**< 结束程序 */
  65.     void    ResizeDraw(bool enable) { m_ResizeDraw = enable; }  /**< 设置在窗口改变大小的时候,可以绘制 */

  66.     Keys    m_Keys;                                             /**< 按键类 */
  67.     /** 构造函数 */
  68.     GLApplication(const char * class_name); 
  69.     
  70. private:
  71.     /** 程序的主循环 */
  72.     friend int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);
  73.     int     Main(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);

  74.     /** 消息处理回调函数 */
  75.     friend LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  76.     LRESULT Message(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

  77.     static const UINT WM_TOGGLEFULLSCREEN = (WM_USER + 1);      /**< 自定义消息,在切换窗口模式的时候发送 */

  78.     GLWindow    m_Window;                                       /**< Window类 */
  79.     const char* m_ClassName;                                    /**< 程序名 */
  80.     bool        m_IsProgramLooping;                             /**< 程序循环标记,如果为false,则退出程序 */
  81.     bool        m_CreateFullScreen;                             /**< 若为true,则创建全屏模式 */
  82.     bool        m_IsVisible;                                    /**< 窗口是否可见 */
  83.     bool        m_ResizeDraw;                                   /**< 是否在改变大小时,调用绘制函数 */
  84.     DWORD       m_LastTickCount;                                /**< 上一次计时器的值 */
  85. };

  86. #endif  // __GLFRAMEWORK_H__
  1. //======================================================================
  2. /**
  3. *  @file  Framework.cpp
  4. *
  5. *  项目描述: OpenGL程序框架演示
  6. *  文件描述:  键盘类和程序框架类 
  7. *  适用平台: Windows98/2000/NT/XP
  8. *  
  9. *   
  10. *  你必须在你的继承类中完成以下函数的实现
  11. *                                                                           
  12. *  GLApplication * GLApplication::Create(const char * class_name)       
  13. *       创建你的子类的一个实例     
  14. *                                                                           
  15. *  bool Init();                                                     
  16. *       执行所有的初始化工作,如果成功函数返回true                         
  17. *                                                                           
  18. *  void Uninit();                                                   
  19. *       执行所有的卸载工作                                       
  20. *                                                                           
  21. *  void Update(DWORD milliseconds);                                     
  22. *       执行所有的更新操作,传入的参数为两次操作经过的时间,以毫秒为单位
  23. *                                                                           
  24. *  void Draw();                                                         
  25. *       执行所有的绘制操作
  26. */                                                                          
  27. //======================================================================

  28. #include "GLFrame.h"                                                    /**< 包含Framework.h头文件 */
  29. //#include "ScreenDlg.h"                                                  /**< 包含ScreenDlg.h头文件 */

  30. #include                                                       /**< 包含OpenGL头文件 */
  31. #include                                                      


  32. /** 主程序入口 */
  33. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
  34. {
  35.     int ret = -1;
  36.     GLApplication * appl = GLApplication::Create("OpenGL");         /**< 创建程序类 */
  37.     if (appl != 0)
  38.     {
  39.         ret = appl->Main(hInstance, hPrevInstance, lpCmdLine, nCmdShow);/**< 执行程序主循环 */
  40.         delete appl;                                                    /**< 删除程序类(在继承类中,使用GL_Example * example = new GL_Example(class_name);分配了一块内存)*/
  41.     }
  42.     else
  43.     {                                                                   /**< 创建程序出错 */
  44.         MessageBoxA(HWND_DESKTOP, "创建程序出错""Error", MB_OK | MB_ICONEXCLAMATION);
  45.     }
  46.     return ret;
  47. }                                                                       

  48. /** 处理窗口消息 */
  49. LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  50. {
  51.     LONG user_data = GetWindowLong(hWnd, GWL_USERDATA);                 /**< 返回用户自定义的32位的程序附加值 */
  52.     if (user_data == 0)
  53.     {   
  54.         /// 如果程序第一次运行
  55.         if (uMsg == WM_CREATE)                                          /**< 处理窗口创建消息 */
  56.         {                                                               
  57.             /// 返回窗口结构的指针,它保存刚创建的程序实例的类
  58.             CREATESTRUCT * creation = reinterpret_cast(lParam);
  59.             /// 获得程序实例的指针
  60.             GLApplication * appl = reinterpret_cast(creation->lpCreateParams);
  61.             /// 保存程序实例的指针为用户自定义的程序附加值
  62.             SetWindowLong(hWnd, GWL_USERDATA, reinterpret_cast<LONG>(appl));
  63.             appl->m_IsVisible = true;                                   /**< 设置程序可见 */
  64.             return 0;                                                   /**< 返回 */
  65.         }
  66.     }
  67.     else
  68.     {   /// 如果不是第一次窗口,返回程序实例的指针
  69.         GLApplication * appl = reinterpret_cast(user_data);
  70.         return appl->Message(hWnd, uMsg, wParam, lParam);               /**< 调用程序实例自己的消息处理函数 */
  71.     }

  72.     return DefWindowProc(hWnd, uMsg, wParam, lParam);                   /**< 调用默认的窗口消息处理函数 */
  73. }


  74. /** 构造函数 */
  75. GLApplication::GLApplication(const char * class_name)                   
  76. {
  77.     m_ClassName = class_name;                                           /**< 保存类名 */
  78.     m_IsProgramLooping = true;                                          /**< 设置程序循环为true */
  79.     m_CreateFullScreen = true;                                          /**< 使用全屏模式 */
  80.     m_IsVisible = false;                                                /**< 不可见 */
  81.     m_ResizeDraw = false;                                               /**< 在窗口改变大小的时候,不可绘制 */
  82.     m_LastTickCount = 0;
  83. }

  84. void GLApplication::ToggleFullscreen()                                  /**< 切换 全屏/窗口模式 */
  85. {
  86.     PostMessage(m_Window, WM_TOGGLEFULLSCREEN, 0, 0);                   /**< 发送自定的切换消息 */
  87. }

  88. void GLApplication::TerminateApplication()                              /**< 结束程序 */
  89. {
  90.     PostMessage(m_Window, WM_QUIT, 0, 0);                               /**< 发送退出消息 */
  91.     m_IsProgramLooping = false;                                         /**< 停止程序循环 */
  92. }

  93. /** 消息循环 */
  94. LRESULT GLApplication::Message(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  95. {
  96.     switch (uMsg)                                                       /**< 处理不同的Windows消息 */
  97.     {
  98.         case WM_SYSCOMMAND:                                             /**< 截获系统命令 */
  99.             switch (wParam)                                             
  100.             {
  101.                 case SC_SCREENSAVE:                                     /**< 截获屏幕保护启动命令 */
  102.                 case SC_MONITORPOWER:                                   /**< 截获显示其省电模式启动命令 */
  103.                     return 0;                                           /**< 不启用这两个命令 */
  104.                 break;
  105.             }
  106.         break;                                                          /**< 退出 */

  107.         case WM_CLOSE:                                                  /**< 关闭窗口 */
  108.             TerminateApplication();                                     /**< 调用TerminateApplication函数 */
  109.             return 0;                                                   
  110.         break;

  111.         case WM_EXITMENULOOP:
  112.         case WM_EXITSIZEMOVE:
  113.             m_LastTickCount = GetTickCount();                           /**< 更新计数器的值 */
  114.             return 0;
  115.         break;

  116.         case WM_MOVE:
  117.             m_Window.SetPosX(LOWORD(lParam));                           /**< 更新鼠标的坐标 */
  118.             m_Window.SetPosY(HIWORD(lParam));                           
  119.             return 0;
  120.         break;

  121.         case WM_PAINT:
  122.             if (m_ResizeDraw == true)                                   /**< 如果需要重绘 */
  123.             {
  124.                 m_Window.ReshapeGL();                                   /**< 重新设置窗口的大小 */
  125.                 Draw();                                                 /**< 重新绘制 */
  126.                 m_Window.SwapBuffers();                                 /**< 交换前后帧缓存 */
  127.             }
  128.         break;

  129.         case WM_SIZING:                                                 /**< 窗口正在改变大小 */
  130.         {
  131.             RECT * rect = (RECT *)lParam;
  132.             m_Window.SetWidth(rect->right - rect->left);                /**< 设置窗口宽度 */
  133.             m_Window.SetHeight(rect->bottom - rect->top);               /**< 设置窗口高度 */
  134.             return TRUE;
  135.         }
  136.         break;

  137.         case WM_SIZE:                                                   /**< 窗口改变大小后 */
  138.             switch (wParam)                                             /**< 处理不同的窗口状态 */
  139.             {
  140.                 case SIZE_MINIMIZED:                                    /**< 是否最小化? */
  141.                     m_IsVisible = false;                                /**< 如果是,则设置不可见 */
  142.                     return 0;                                           
  143.                 break;

  144.                 case SIZE_MAXIMIZED:                                    /**< 窗口是否最大化? */
  145.                 case SIZE_RESTORED:                                     /**< 窗口被还原? */
  146.                     m_IsVisible = true;                                 /**< 设置为可见 */
  147.                     m_Window.SetWidth(LOWORD(lParam));                  /**< 设置窗口宽度 */
  148.                     m_Window.SetHeight(HIWORD(lParam));                 /**< 设置窗口高度 */
  149.                     m_Window.ReshapeGL();                               /**< 改变窗口大小 */
  150.                     m_LastTickCount = GetTickCount();                   /**< 更新计数器的值 */
  151.                     return 0;                                           
  152.                 break;
  153.             }
  154.         break;                                                          

  155.         case WM_KEYDOWN:                                                /**< 更新按键信息 */
  156.             m_Keys.SetPressed(wParam);                                  
  157.             return 0;                                                   
  158.         break;

  159.         case WM_KEYUP:                                                  /**< 更新释放键信息 */
  160.             m_Keys.SetReleased(wParam);                                 
  161.             return 0;                                                   
  162.         break;

  163.         case WM_TOGGLEFULLSCREEN:                                       /**< 切换 全屏/窗口模式 */
  164.           /*  m_Window.SetFullScreen(!m_Window.GetFullScreen());
  165.             if(!m_Window.GetFullScreen())
  166.                 ShowCursor(true);
  167.             else
  168.                 ShowCursor(false);*/

  169.             m_CreateFullScreen = !m_CreateFullScreen;
  170.             PostMessage(hWnd, WM_QUIT, 0, 0);
  171.         break;                                                          
  172.     }

  173.     return DefWindowProc(hWnd, uMsg, wParam, lParam);                   /**< 调用默认的窗口消息处理函数 */
  174. }

  175. /** 程序的主循环 */
  176. int GLApplication::Main(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
  177. {
  178.     /// 注册一个窗口
  179.     WNDCLASSEX windowClass;                                             /**< 窗口类 */
  180.     ZeroMemory(&windowClass, sizeof(WNDCLASSEX));                       /**< 清空结构为0 */
  181.     windowClass.cbSize          = sizeof(WNDCLASSEX);                   /**< 窗口结构的大小 */
  182.     windowClass.style           = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;   /**< 设置窗口类型为,移动时重画,并为窗口取得DC */
  183.     windowClass.lpfnWndProc     = (WNDPROC)(WindowProc);                /**< WndProc处理消息 */
  184.     windowClass.hInstance       = hInstance;                            /**< 设置实例 */
  185.     windowClass.hbrBackground   = (HBRUSH)(COLOR_APPWORKSPACE);         /**< 设置背景 */
  186.     windowClass.hCursor         = LoadCursor(NULL, IDC_ARROW);          /**< 载入光标 */
  187.     windowClass.lpszClassName   = m_ClassName;                          /**< 设置类名 */
  188.     if (RegisterClassEx(&windowClass) == 0)                             /**< 尝试注册窗口类 */
  189.     {                                                                   /**< NOTE: Failure, Should Never Happen */
  190.         MessageBoxA(HWND_DESKTOP, "注册窗口失败!""Error", MB_OK | MB_ICONEXCLAMATION);
  191.         return -1;                                                      /**< 退出并返回FALSE */
  192.     }

  193.     // 询问是否在全屏状态下运行?
  194.     if (MessageBoxA(HWND_DESKTOP, "你想在全屏状态下运行么 ?""是否全屏运行?", MB_YESNO | MB_ICONQUESTION) == IDNO)
  195.     {
  196.         m_CreateFullScreen = false;                                     /**< m_CreateFullScreen记录当前的显示模式为窗口 */
  197.     }
  198.     //ScreenDlg sd;
  199.     //sd.SetupWindow(&m_Window);
  200.     //m_CreateFullScreen = m_Window.GetFullScreen();
  201.     while (m_IsProgramLooping)                                          /**< 循环直道WM_QUIT退出程序 */
  202.     {                                                                   
  203.         /// 创建一个窗口
  204.         if (m_Window.Create("OpenGL 3D游戏编程——框架", m_ClassName,m_CreateFullScreen, hInstance, this) == true)
  205.         {   
  206.             
  207.             /// 如果初始化失败,则退出
  208.             if (Init() == false)                                    /**< 调用自定义的初始化函数 */
  209.             {                                                           /**< 失败 */
  210.                 TerminateApplication();                                 /**< 关闭窗口退出程序 */
  211.             }
  212.             else                                                        /**< 成功开始消息循环 */
  213.             {                                                            
  214.                 MSG msg;                                                /**< Window消息结构 */ 
  215.                 bool isMessagePumpActive = true;                        /**< 当消息不为空时,处理消息循环 */
  216.                 m_LastTickCount = GetTickCount();                       /**< 返回当前的计时器的值 */
  217.                 m_Keys.Clear();                                         /**< 清空所有的按键信息 */
  218.                 while (isMessagePumpActive == true)                     /**< 当消息不为空时,处理消息循环 */
  219.                 {                                                       /**< 成功创建窗口,检测窗口消息 */
  220.                     if (PeekMessage(&msg, m_Window, 0, 0, PM_REMOVE) != 0)
  221.                     {                                                   
  222.                         /// 检测是否为WM_QUIT消息
  223.                         if (msg.message != WM_QUIT)                     
  224.                         {
  225.                             DispatchMessage(&msg);                      /**< 如果不是发送消息到消息回调函数中处理 */
  226.                         }
  227.                         else                                            
  228.                         {
  229.                             isMessagePumpActive = false;                /**< 如果是,则退出 */
  230.                         }
  231.                     }
  232.                     /// 如果没有消息
  233.                     else                                                
  234.                     {
  235.                         if (m_IsVisible == false)                       /**< 如果窗口不可见 */
  236.                         {
  237.                             WaitMessage();                              /**< 暂停程序,等待消息 */
  238.                         }
  239.                         else                                            /**< 如果窗口可见 */
  240.                         {                                               /**< 执行消息循环 */
  241.                             DWORD tickCount = GetTickCount();           /**< 返回计时器的当前值 */
  242.                             Update(tickCount - m_LastTickCount);        /**< 调用用户自定义的更新函数 */
  243.                             m_LastTickCount = tickCount;                /**< 重新设置上一次,计数器的值 */
  244.                             Draw();                                     /**< 调用用户自定义的绘制函数 */
  245.                             m_Window.SwapBuffers();                     /**< 交换前后帧缓存 */
  246.                         }
  247.                     }
  248.                 }                                                       /**< 如果isMessagePumpActive == true,则循环 */
  249.             }                                                           
  250.                                                                         /**< 程序结束 */
  251.             Uninit();                                               /**< 用户自定义的卸载函数 */
  252.             m_Window.Destroy();                                         /**< 删除窗口 */
  253.         }
  254.         else                                                            /**< 如果创建窗口失败 */
  255.         {                                                               
  256.             MessageBoxA(HWND_DESKTOP, "创建OpenGL窗口错误""Error", MB_OK | MB_ICONEXCLAMATION);
  257.             m_IsProgramLooping = false;                                 /**< 停止程序循环 */
  258.         }
  259.     }                                                                   

  260.     UnregisterClassA(m_ClassName, hInstance);                           /**< 取消注册的窗口 */
  261.     return 0;
  262. }

附上实例程序:

  1. //=========================================================================
  2. /**
  3. *  @file  Example.h
  4. *
  5. *  项目描述: OpenGL程序框架演示
  6. *  文件描述:  具体实例类 
  7. *  适用平台: Windows98/2000/NT/XP
  8. *  
  9. *
  10. *  在这个类中您必须重载如下几个虚函数
  11. *                                                                                               
  12. *   virtual bool Init();                                                        
  13. *       执行所有的初始化工作,如果成功函数返回true                         
  14. *                                                                           
  15. *   virtual void Uninit();                                                  
  16. *       执行所有的卸载工作                                       
  17. *                                                                           
  18. *   virtual void Update(DWORD milliseconds);                                        
  19. *       执行所有的更新操作,传入的参数为两次操作经过的时间,以毫秒为单位
  20. *                                                                           
  21. *   virtual void Draw();                                                            
  22. *       执行所有的绘制操作
  23. */
  24. //=========================================================================

  25. #ifndef __EXAMPLE_H__
  26. #define __EXAMPLE_H__


  27. #include "GLFrame.h"                                                /**< 包含基本的框架类 */

  28. /** 从GL_Application派生出一个子类 */
  29. class Example : GLApplication                               
  30. {
  31. public:
  32.     bool    Init();                                     /**< 执行所有的初始化工作,如果成功函数返回true */
  33.     void    Uninit();                                       /**< 执行所有的卸载工作 */
  34.     void    Update(DWORD milliseconds);                         /**< 执行所有的更新操作,传入的参数为两次操作经过的时间,以毫秒为单位 */
  35.     void    Draw();                                             /**< 执行所有的绘制操作 */

  36. private:
  37.     friend class GLApplication;                             /**< 父类为它的一个友元类,可以用来创建程序的实例,见函数GL_Application * GL_Application::Create(const char * class_name) */
  38.     Example(const char * class_name);                       /**< 构造函数 */
  39. /** 用户自定义的程序变量 */
  40.     float   m_Angle;                                            /**< 使用它来旋转三角形 */
  41. };


  42. #endif  // __EXAMPLE_H__
  1. //=========================================================================
  2. /**
  3. *  @file  Example.cpp
  4. *
  5. *  项目描述: OpenGL程序框架演示
  6. *  文件描述:  具体实例类 
  7. *  适用平台: Windows98/2000/NT/XP
  8. *  
  9. *
  10. *  在这个类中您必须重载如下几个虚函数
  11. *                                                                                               
  12. *   virtual bool Init();                                                        
  13. *       执行所有的初始化工作,如果成功函数返回true                         
  14. *                                                                           
  15. *   virtual void Uninit();                                                  
  16. *       执行所有的卸载工作                                       
  17. *                                                                           
  18. *   virtual void Update(DWORD milliseconds);                                        
  19. *       执行所有的更新操作,传入的参数为两次操作经过的时间,以毫秒为单位
  20. *                                                                           
  21. *   virtual void Draw();                                                            
  22. *       执行所有的绘制操作
  23. */
  24. //=========================================================================

  25. #include "Example.h"                                            /**< 包含头文件 */

  26. #include                                               /**< 包含OpenGL头文件 */
  27. #include                                              
  28. #include                                            


  29. #pragma comment(lib, "opengl32.lib")                            /**< 包含OpenGL链接库文件 */
  30. #pragma comment(lib, "glu32.lib")                           
  31. #pragma comment(lib, "glaux.lib")                           


  32. /** 创建一个程序的实例 */
  33. GLApplication * GLApplication::Create(const char * class_name)
  34. {
  35.     Example * example = new Example(class_name);
  36.     return reinterpret_cast(example);
  37. }


  38. /** 构造函数 */
  39. Example::Example(const char * class_name) : GLApplication(class_name)
  40. {
  41.   /// 初始化用户自定义的程序变量
  42.     m_Angle = 0.0f;                                             /**< 设置初始角度为0 */
  43. }

  44. /** 初始化OpenGL */
  45. bool Example::Init()                                    
  46. {
  47. /** 用户自定义的初始化过程 */
  48.     glClearColor(0.0f, 0.0f, 0.0f, 0.5f);                       
  49.     glClearDepth(1.0f);                                         
  50.     glDepthFunc(GL_LEQUAL);                                     
  51.     glEnable(GL_DEPTH_TEST);                                    
  52.     glShadeModel(GL_SMOOTH);                                    
  53.     glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);          
  54.     ResizeDraw(true);                                           /**< 改变OpenGL窗口大小,直接调用子类的函数 */

  55.     return true;                                                /**< 成功返回 */
  56. }

  57. /** 用户自定义的卸载函数 */
  58. void Example::Uninit()                                  
  59. {
  60. /** 用户自定义的卸载过程 */
  61. ///......
  62. ///......
  63. }

  64. /** 程序更新函数 */
  65. void Example::Update(DWORD milliseconds)                        
  66. {
  67.     if (m_Keys.IsPressed(VK_ESCAPE) == true)                    /**< 按ESC退出 */
  68.     {
  69.         TerminateApplication();                                 
  70.     }

  71.     if (m_Keys.IsPressed(VK_F1) == true)                        /**< 按F1切换窗口/全屏模式 */
  72.     {
  73.         ToggleFullscreen();                                     
  74.     }
  75. /** 用户自定义的更新过程 */
  76.     m_Angle += (float)(milliseconds) / 15.0f;                   /**< 更新旋转的角度 */
  77.      
  78. }

  79. /** 绘制函数 */
  80. void Example::Draw()                                            
  81. {
  82. /** 用户自定义的绘制过程 */
  83.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);         
  84.     glLoadIdentity();                                           
  85.     glTranslatef(0.0f, 0.0f, -6.0f);                            
  86.     glRotatef(m_Angle, 0.0f, 1.0f, 0.0f);                       
  87.     glRotatef(m_Angle * 0.7f, -1.0f, 0.0f, 0.0f);               

  88.     for (int rot1 = 0; rot1 < 2; rot1++)                        /**< 绘制四个交错的三角形(想的很巧妙啊)*/
  89.     {
  90.         glRotatef(90.0f, 0.0f, 1.0f, 0.0f);                     
  91.         glRotatef(180.0f, 1.0f, 0.0f, 0.0f);                    
  92.         for (int rot2 = 0; rot2 < 2; rot2++)                    
  93.         {
  94.             glRotatef(180.0f, 0.0f, 1.0f, 0.0f);                
  95.             glBegin(GL_TRIANGLES);                              
  96.                 glColor3f(1.f, 0.f, 0.f);   glVertex3f( 0.0f,  1.0f, 0.0f);
  97.                 glColor3f(0.f, 1.f, 0.f);   glVertex3f(-1.0f, -1.0f, 1.0f);
  98.                 glColor3f(0.f, 0.f, 1.f);   glVertex3f( 1.0f, -1.0f, 1.0f);
  99.             glEnd();                                            
  100.         }
  101.     }
  102.     glFlush();                                                  /**< 强制执行所有的OpenGL命令 */
  103. }

注意的几点是:

1.在VS2005中建立项目时,须先建立控制台应用程序,再点选空项目,否则调试时会跑到 crt0.c 程序中。

2.需要将相应库文件放在源文件同一目录下。

3.配置属性->常规->字符集 中点选使用多字节字符集,否则若使用Unicode字符集,一些windows函数调用会出错。

4.配置属性->调试->生成调试信息 点选(是/Debug).

5.配置属性->清单工具->常规->使用FAT32解决办法 点选是。


你可能感兴趣的:(opengl)