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

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