//========================================================
/*
* @file stdafx.h
*
* 项目描述: OpenGL程序框架演示
* 文件描述: 标准系统包含文件的包含文件,或是经常使用但不常更改的特定于项目的包含文件
* 适用平台: Windows XP/Win7
*
* 作 者: 孤舟钓客
* 电子邮件:
* 创建日期: 2010-10-07
*
*/
//========================================================
#pragma once
#define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的信息
// Windows 头文件:
#include
// C 运行时头文件
#include
#include
#include
#include
// TODO: 在此处引用程序需要的其他头文件
#include
#include
#include
#include
#include
#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