OpenGL面向对象程序框架

//========================================================
/*
* @file stdafx.h
*
* 项目描述: OpenGL程序框架演示
* 文件描述: 标准系统包含文件的包含文件,或是经常使用但不常更改的特定于项目的包含文件
* 适用平台: Windows XP/Win7

* 作 者: 孤舟钓客
* 电子邮件: 
* 创建日期: 2010-10-07
*
*/
//========================================================

#pragma once

#define WIN32_LEAN_AND_MEAN             // 从 Windows 头文件中排除极少使用的信息
// Windows 头文件:
#include <windows.h>

// C 运行时头文件
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>

// TODO: 在此处引用程序需要的其他头文件
#include <atlstr.h>
#include <assert.h>
#include <gl\gl.h>       // OpenGL32库的头文件
#include <gl\glu.h>       // GLu32库的头文件
#include <gl\glaux.h>      // GLaux库的头文件
#include "resource.h"

#pragma comment(lib, "winmm.lib")
#pragma comment(lib, "opengl32.lib") // OpenGL32连接库
#pragma comment(lib, "glu32.lib")   // GLu32连接库
#pragma comment(lib, "glaux.lib")   // GLaux连接库

//========================================================
/*
* @file GLWindows.h
*
* 项目描述: OpenGL程序框架演示
* 文件描述: OpenGL窗口类
* 适用平台: Windows XP/Win7

* 作 者: 孤舟钓客
* 电子邮件: 
* 创建日期: 2010-10-07
*
*/
//========================================================
#pragma once
#include "stdafx.h"

//windows窗口类
class GLWindow               
{
public:
GLWindow();             // 构造函数
~GLWindow();            // 析构函数

bool Create(const char *window_title, const char *class_name, bool fullscreen, 
   HINSTANCE h_instance, LPVOID lpParam);     // 创建OpenGL窗口
void Destroy();            // 删除OpenGL窗口
bool ChangeScreenSetting();         // 改变窗口的显示设置
void ReshapeGL();           // 当窗口大小改变时,通知OpenGL调整大小
void SwapBuffers() { ::SwapBuffers(m_hDC); }    // 交换缓冲区

// 设置窗口左上角的位置
void SetPosX(int x);
void SetPosX(unsigned short x) { SetPosX((int)x); }  
void SetPosY(int y);
void SetPosY(unsigned short y) { SetPosY((int)y); }

// 返回窗口的大小
int GetWidth();
int GetHeight();

// 设置窗口的大小
void SetWidth(int width);
void SetHeight(int height);

// 返回窗口左上角的位置
int GetPosX();
int GetPosY();

// 设置窗口的颜色位深
void SetHiColor() { m_BitsPerPixel = 16; }
void SetTrueColor() { m_BitsPerPixel = 32; }

// 重载运算符,可以让GL_Window m_Window声明后的m_Window作为窗口句柄使用
operator HWND() { return m_hWnd; }

private:
HWND m_hWnd;            // 窗口句柄
HDC   m_hDC;            // 设备描述表
HGLRC m_hRC;            // OpenGL渲染描述表

int   m_WindowPosX;          // 窗口的左上角的X位置
int   m_WindowPosY;          // 窗口的左上角的Y位置
int   m_WindowWidth;          // 窗口的宽度
int   m_WindowHeight;          // 窗口的高度
int   m_ScreenWidth;          // 全屏的宽度
int   m_ScreenHeight;          // 全屏的高度
int   m_BitsPerPixel;          // 颜色位深
bool m_IsFullScreen;          // 是否全屏
};

// GLWindow.cpp

#include "GLWindow.h"

// 构造函数
GLWindow::GLWindow(void)
{
m_WindowPosX = 0;          // 窗口的左上角的X位置
m_WindowPosY = 0;          // 窗口的左上角的Y位置
m_WindowWidth = 800;          // 窗口的宽度
m_WindowHeight = 600;          // 窗口的高度
m_ScreenWidth = 1280;          // 全屏的宽度
m_ScreenHeight = 800;          // 全屏的高度
m_BitsPerPixel = 16;          // 颜色位深
m_IsFullScreen = false;         // 不使用全屏

m_hWnd = 0;
m_hDC = 0;
m_hRC = 0;
}

GLWindow::~GLWindow(void)
{
}

// 返回窗口的大小
int GLWindow::GetWidth()
{
if (m_IsFullScreen == true)
   return m_ScreenWidth;
else
   return m_WindowWidth;
}
int GLWindow::GetHeight()
{
if (m_IsFullScreen == true)
   return m_ScreenHeight;
else
   return m_WindowHeight;
}

// 设置窗口的大小
void GLWindow::SetWidth(int width)
{
if (m_IsFullScreen == true)
   m_ScreenWidth = width;
else
   m_WindowWidth = width;
}
void GLWindow::SetHeight(int height)
{
if (m_IsFullScreen == true)
   m_ScreenHeight = height;
else
   m_WindowHeight = height;
}

// 返回窗口左上角的位置
int GLWindow::GetPosX()
{
if (m_IsFullScreen == false)
   return m_WindowPosX;
return 0;
}
int GLWindow::GetPosY()
{
if (m_IsFullScreen == false)
   return m_WindowPosY;
return 0;
}

// 设置窗口左上角的位置
void GLWindow::SetPosX(int x)
{
if (m_IsFullScreen == false)
   m_WindowPosX = x;
}
void GLWindow::SetPosY(int y)
{
if (m_IsFullScreen == false)
   m_WindowPosY = y;
}

// 当窗口大小改变时,通知OpenGL调整大小
void GLWindow::ReshapeGL()
{
GLsizei width = GetWidth();
GLsizei height = GetHeight();
glViewport(0, 0, width, height);       // 重新设置视口
glMatrixMode(GL_PROJECTION);         
glLoadIdentity();             
gluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 1.0f, 100.0f); 
glMatrixMode(GL_MODELVIEW);           
glLoadIdentity();             
}

// 改变窗口的显示设置
bool GLWindow::ChangeScreenSetting()
{
DEVMODE dmScreenSettings;         // 设备模式
ZeroMemory(&dmScreenSettings, sizeof(DEVMODE));    // 清零结构
dmScreenSettings.dmSize    = sizeof(DEVMODE);   // 结构大小
dmScreenSettings.dmPelsWidth = GetWidth();    // 设置宽度
dmScreenSettings.dmPelsHeight = GetHeight();    // 设置高度
dmScreenSettings.dmBitsPerPel = m_BitsPerPixel;   // 设置位深度
dmScreenSettings.dmFields   = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;

// 改变显示模式
if (ChangeDisplaySettings(&dmScreenSettings, 0) != DISP_CHANGE_SUCCESSFUL)
   return false;           // 如果失败,返回false

return true;            // 成功返回
}

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

DWORD windowStyle = WS_OVERLAPPEDWINDOW & ~WS_SIZEBOX & ~WS_MAXIMIZEBOX; 
                // 定义窗口类型,常规设定,去掉最大化按钮,不能改变窗体大小
DWORD windowExtendedStyle = WS_EX_APPWINDOW;

if (m_IsFullScreen == true)         // 如果为全屏模式,尝试转化为全屏模式
{
   if (ChangeScreenSetting() == false)
   {              // 全屏模式转换失败,弹出对话框提示,并尝试窗口模式
    MessageBox(HWND_DESKTOP, "模式转换失败.\n在窗口模式下运行.", "Error", MB_OK | MB_ICONEXCLAMATION);
    m_IsFullScreen = false;        // 设置为窗口模式
   }
   else             // 如果为窗口模式
   {
    ShowCursor(false);         // 隐藏鼠标
    windowStyle = WS_POPUP;        // 设置窗口模式为顶层窗口
    windowExtendedStyle |= WS_EX_TOPMOST;      
   }                
}

// 调整我们窗口的大小,使其客户区的大小为我们设置的大小
RECT windowRect = { GetPosX(), GetPosY(), GetPosX() + GetWidth(), GetPosY() + GetHeight() };
if (m_IsFullScreen == false)        // 在窗口模式下使用

   windowExtendedStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; 
                // 使窗口具有3D外观
   int wid = GetSystemMetrics(SM_CXSCREEN);    // 获取当前屏幕宽 
   int hei = GetSystemMetrics(SM_CYSCREEN);    // 获取当前屏幕高
   nX = (wid - GetWidth()) / 2;       // 计算窗口居中用
   nY = (hei - GetHeight()) / 2;   
  
   AdjustWindowRectEx(&windowRect, windowStyle, 0, windowExtendedStyle);
                // 调整我们窗口的大小,使其客户区的大小为我们设置的大小
   // 判断窗口的左上角是否隐藏在桌面外
   if (windowRect.left < 0)        // 如果窗口X座标为负,移动座标到0处,并调整窗口的位置
   {
    windowRect.right -= windowRect.left;      
    windowRect.left = 0;          
   }
   if (windowRect.top < 0)         // 如果窗口Y座标为负,移动座标到0处,并调整窗口的位置
   {
    windowRect.bottom -= windowRect.top;      
    windowRect.top = 0;           
   }
}

// 创建窗口
m_hWnd = CreateWindowEx(windowExtendedStyle,    // 窗口的扩展风格
   class_name,            // 窗口的类名
   window_title,           // 窗口标题
   windowStyle,           // 窗口的风格
   nX,nY,             // 窗口的左上角位置
   windowRect.right - windowRect.left,      // 窗口的宽度
   windowRect.bottom - windowRect.top,      // 窗口的高度
   HWND_DESKTOP,           // 窗口的父窗口为桌面
   0,              // 无菜单
   h_instance,            // 传入窗口的实例句柄
   lpParam);            // 传入程序类参数

while (m_hWnd != 0)           // 窗口是否创建成功
{
   m_hDC = GetDC(m_hWnd);         // 返回窗口的设备描述表
   if (m_hDC == 0)           // 如果为空
    break;

   GLuint PixelFormat = ChoosePixelFormat(m_hDC, &pfd);// 查找一个兼容的像素格式
   if (PixelFormat == 0)
    break;
   if (SetPixelFormat(m_hDC, PixelFormat, &pfd) == false)
                // 设置像素格式
    break;
  
   m_hRC = wglCreateContext(m_hDC);      // 创建OpenGL的渲染描述表
   if (m_hRC == 0)           // 如果为空
    break;

   if (wglMakeCurrent(m_hDC, m_hRC) == false)    // 设置当前的OpenGL的渲染对象为当前的窗口
    break;

   ShowWindow(m_hWnd, SW_NORMAL);       // 显示窗口
   ReshapeGL();           // 告诉OpenGL调整窗口大小
   return true;           // 成功返回 
}

Destroy();             // 释放资源
return false;            // 返回失败
}

// 删除OpenGL窗口
void GLWindow::Destroy()         
{
if (m_hWnd != 0)           // 窗口句柄是否存在
{
   if (m_hDC != 0)           // 窗口设备描述表是否存在
   {
    wglMakeCurrent(m_hDC, 0);       // 设置当前的OpenGL的渲染对象为空NULL
    if (m_hRC != 0)          // OpenGL的渲染描述表是否存在
    {
     wglDeleteContext(m_hRC);      // 释放OpenGL的渲染描述表
     m_hRC = 0;          // 设置OpenGL的渲染描述表为0
    }
    ReleaseDC(m_hWnd, m_hDC);       // 释放窗口的设备描述表
    m_hDC = 0;           // 设置窗口的设备描述表为0
   }
   DestroyWindow(m_hWnd);         // 删除窗口
   m_hWnd = 0;            // 设置窗口句柄为0
}

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

// 待续

本文出自http://hi.baidu.com/guzhou_diaoke/item/8082bef982405b613c1485cf

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章