//========================================================
/*
* @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