19,469
社区成员
发帖
与我相关
我的任务
分享
//GLWindows.h
#ifndef _GL_WINDOW_H_
#define _GL_WINDOW_H_
#include <Windows.h>
class GL_Window
{
public:
GL_Window(); //构造函数
bool Create(const char *window_title,bool full_screen,
const char *class_name,HINSTANCE h_Instance,LPVOID lpParam); //创建窗口
void Destroy(); //删除窗口
bool ChangeScreenSetting(); //改变窗口显示设置
void ReshapeGL(); //当窗口大小变化,通知GL
void SwapBuffers(){::SwapBuffers(m_hDC);} //
/*设置窗口左上角位置*/
void SetPosX(int x){m_WindowPosX=x;}
void SetPosX(unsigned short x){SetPosX((signed short)x);}
void SetPosY(int y){m_WindowPosY=y;}
void SetPosY(unsigned short y){SetPosX((signed short)y);}
/*返回窗口的大小*/
int GetWidth(){return m_WindowWidth;}
int GetHeight(){return m_WindowHeight;}
/*设置窗口的大小*/
void SetWidth(int width){m_WindowWidth=width;}
void SetHeight(int height){m_WindowHeight=height;}
/*返回窗口左上角的位置*/
int GetPosX(){return m_WindowPosX;}
int GetPosY(){return m_WindowPosY;}
/*设置窗口的颜色位深*/
void SetHiColor(){m_BitsPerPixel=16;}
void SetTrueColor(){m_BitsPerPixel=32;}
/*重载运算符*/
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; //是否全屏
};
#endif
//example.cpp
#include "example.h"
#include <gl\glew.h>
#include <gl\GLAUX.H>
GL_Application* GL_Application::Create(const char *class_name)
{
Example *example=new Example(class_name);
return reinterpret_cast<GL_Application*>(example);
}
bool Example::Initialize()
{
glClearColor(0.0f,0.0f,0.0f,0.5f);
glClearDepth(1.0f);
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
ResizeDraw(true);
return true;
}
void Example::Draw()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f,0.0f,-7.0f);
glRotatef(m_Angle,0.0f,1.0f,0.0f);
glColor3f(0.0f,0.0f,1.0f);
auxWireTeapot(2.0);
glFlush();
}
void Example::Update(DWORD milliseconds)
{
if(m_Keys.IsPressed(VK_ESCAPE)==true)
{
TerminateApplication();
}
if(m_Keys.IsPressed(VK_F1)==true)
{
ToggleFullscreen();
}
m_Angle+=(float)(milliseconds)/15.0f;
}
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
int ret=-1;
GL_Application *appl=GL_Application::Create("OP!fyzzy!");
if(appl!=0)
{
ret=appl->Main(hInstance,hPrevInstance,lpCmdLine,nCmdShow);
delete appl;
}
else
{
MessageBox(HWND_DESKTOP,"创建程序出错","Error",MB_OK | MB_ICONEXCLAMATION);
}
return ret;
}
int GL_Application::Main(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
WNDCLASSEX windowClass;
ZeroMemory(&windowClass,sizeof(WNDCLASSEX));
windowClass.cbSize=sizeof(WNDCLASSEX);
windowClass.style=CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
windowClass.lpfnWndProc=(WNDPROC)(WindowProc);
windowClass.hInstance=hInstance;
windowClass.hbrBackground=(HBRUSH)(COLOR_APPWORKSPACE);
windowClass.hCursor=LoadCursor(NULL,IDC_ARROW);
windowClass.lpszClassName=m_ClassName;
if(RegisterClassEx(&windowClass)==0)
{
MessageBox(HWND_DESKTOP,"注册窗口失败","Error",MB_OK | MB_ICONEXCLAMATION);
return -1;
}
if(MessageBox(HWND_DESKTOP,"全屏?","?",MB_YESNO | MB_ICONQUESTION)==IDNO)
{
m_CreateFullScreen=false;
}
while(m_IsProgramLooping)
{
if(m_Window.Create("OO",m_CreateFullScreen,m_ClassName,hInstance,this)==true)
{
if(Initialize()==false)
{
TerminateApplication();
}
else
{
MSG msg;
bool isMessagePumpActive=true;
m_LastTickCount=GetTickCount();
m_Keys.Clear();
while(isMessagePumpActive==true)
{
if(PeekMessage(&msg,m_Window,0,0,PM_REMOVE)!=0)
{
if(msg.message!=WM_QUIT)
{
DispatchMessage(&msg);
}
else
{
isMessagePumpActive=false;
}
}
else
{
if(m_IsVisible==false)
{
WaitMessage();
}
else
{
DWORD tickCount=GetTickCount();
Update(tickCount-m_LastTickCount);
m_LastTickCount=tickCount;
Draw();
m_Window.SwapBuffers();
}
}
}
}
DeInitialize();
m_Window.Destroy();
}
else
{
MessageBox(HWND_DESKTOP,"GL窗口错误","ERROR",MB_OK | MB_ICONEXCLAMATION);
}
}
UnregisterClass(m_ClassName,hInstance);
return 0;
}
LRESULT CALLBACK WindowProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
LONG user_data=GetWindowLong(hWnd,GWL_USERDATA);
if(user_data==0)
{
if(uMsg==WM_CREATE)
{
CREATESTRUCT *creation=reinterpret_cast<CREATESTRUCT*>(lParam);
GL_Application *appl=reinterpret_cast<GL_Application*>(creation->lpCreateParams);
SetWindowLong(hWnd,GWL_USERDATA,reinterpret_cast<LONG>(appl));
appl->m_IsVisible=true;
return 0;
}
}
else
{
GL_Application *appl=reinterpret_cast<GL_Application*>(user_data);
return appl->Message(hWnd,uMsg,wParam,lParam);
}
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
//GLWindows.cpp
#include "GLWindows.h"
#include <gl\glut.h>
/*构造函数*/
GL_Window::GL_Window()
{
m_WindowPosX=0;
m_WindowPosY=0;
m_WindowWidth=800;
m_WindowHeight=600;
m_ScreenWidth=1366;
m_ScreenHeight=769;
m_BitsPerPixel=32;
m_IsFullScreen=false;
m_hWnd=0;
m_hDC=0;
m_hRC=0;
}
/*创建Windows窗口*/
bool GL_Window::Create(const char *window_title,bool full_screen,const char *class_name,
HINSTANCE h_Instance,LPVOID lpParam)
{
m_IsFullScreen=full_screen;
PIXELFORMATDESCRIPTOR pfd=
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW |
PFD_SUPPORT_OPENGL |
PFD_STEREO |
PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
m_BitsPerPixel,
0,0,0,0,0,0,
0,
0,
0,
0,0,0,0,
32,
0,
0,
PFD_MAIN_PLANE,
0,
0,0,0
};
DWORD windowStyle=WS_OVERLAPPEDWINDOW;
DWORD windowExtendedStyle=WS_EX_APPWINDOW;
if(m_IsFullScreen==true)
{
if(ChangeScreenSetting()==false)
{
MessageBox(HWND_DESKTOP,"全屏错误,窗口运行","e",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)
{
AdjustWindowRectEx(&windowRect,windowStyle,0,windowExtendedStyle);
if(windowRect.left<0)
{
windowRect.right-=windowRect.left;
windowRect.left=0;
}
if(windowRect.top<0)
{
windowRect.bottom-=windowRect.top;
windowRect.top=0;
}
}
/*创建窗口*/
m_hWnd=CreateWindowEx(windowExtendedStyle,
class_name,
window_title,
windowStyle,
windowRect.left,windowRect.top,
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);
if(m_hRC==0)
{
break;
}
if(wglMakeCurrent(m_hDC,m_hRC)==false)
{
break;
}
ShowWindow(m_hWnd,SW_NORMAL);
ReshapeGL();
return true;
}
Destroy();
return false;
}
/*改变窗口的显示设置*/
bool GL_Window::ChangeScreenSetting()
{
DEVMODE dmScreenSettings;
ZeroMemory(&dmScreenSettings,sizeof(DEVMODE));
dmScreenSettings.dmSize=sizeof(DEVMODE);
dmScreenSettings.dmPanningWidth=GetWidth();
dmScreenSettings.dmPanningHeight=GetHeight();
dmScreenSettings.dmBitsPerPel=m_BitsPerPixel;
dmScreenSettings.dmFields=DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
//改变显示模式
if(ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
{
return false;
}
return true;
}
/*窗口大小改变时,通知OpenGL*/
void GL_Window::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();
}
/*删除OpenGL窗口*/
void GL_Window::Destroy()
{
if(m_hWnd!=0)
{
if(m_hDC!=0)
{
wglMakeCurrent(m_hDC,0);
if(m_hRC!=0)
{
wglDeleteContext(m_hRC);
m_hRC=0;
}
ReleaseDC(m_hWnd,m_hDC);
m_hDC=0;
}
DestroyWindow(m_hWnd);
m_hWnd=0;
}
if(m_IsFullScreen)
{
ChangeDisplaySettings(NULL,0);
ShowCursor(true);
}
}
//example.h
#ifndef _EXAMPLE_H_
#define _EXAMPLE_H_
#include "GLApplication.h"
class Example:GL_Application
{
public:
bool Initialize(); //所有的初始化
void DeInitialize(); //所有的卸载
void Update(DWORD milliseconds); //所有的更新
void Draw(); //所有的绘制
private:
friend class GL_Application;
Example(const char *class_name);
float m_Angle;
};
#endif
//GLApplication.h
#ifndef _GLAPPLICATION_H_
#define _GLAPPLICATION_H_
#include <Windows.h>
#include "GLWindows.h"
class Keys
{
public:
Keys(){Clear();}
void Clear(){ZeroMemory(&m_KeyDown,sizeof(m_KeyDown));} //清除所有按键信息
bool IsPressed(unsigned int key){return (key<MAX_KEYS)?(m_KeyDown[key]==true):false;} //判断某个键按下
void SetPressed(unsigned int key){if(key<MAX_KEYS)m_KeyDown[key]=true;}
void SetReleased(unsigned int key){if(key<MAX_KEYS)m_KeyDown[key]=false;}
private:
static const unsigned int MAX_KEYS=256;
bool m_KeyDown[MAX_KEYS];
};
class GL_Application
{
public:
static GL_Application *Create(const char *class_name);
virtual ~GL_Application(){};
protected:
virtual bool Initialize()=0;
virtual void DeInitialize()=0;
virtual void Update(DWORD milliseconds)=0; //OpenGl程序更新
virtual void Draw()=0; //绘制场景
/*通用函数*/
void ToggleFullscreen(); //切换全屏/窗口
void TerminateApplication(); //结束程序
void ResizeDraw(bool enable){m_ResizeDraw=enable;} //设置在窗口改变大小的时候,可以绘制
Keys m_Keys;
GL_Application(const char *class_name); //构造函数
private:
friend int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow);
int Main(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int cCmdLine);
friend LRESULT CALLBACK WindowProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
LRESULT Message(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
static const UINT WM_TOGGLEFULLSCREEN=(WM_USER+1);
GL_Window m_Window;
const char *m_ClassName;
bool m_IsProgramLooping;
bool m_CreateFullScreen;
bool m_IsVisible;
bool m_ResizeDraw;
DWORD m_LastTickCount;
};
/*构造函数*/
GL_Application::GL_Application(const char *class_name)
{
m_ClassName=class_name;
m_IsProgramLooping=true;
m_CreateFullScreen=true;
m_IsVisible=false;
m_ResizeDraw=false;
m_LastTickCount=0;
}
/*窗口切换函数*/
void GL_Application::ToggleFullscreen()
{
PostMessage(m_Window,WM_TOGGLEFULLSCREEN,0,0); //发送自定的切换消息
}
/*结束程序*/
void GL_Application::TerminateApplication()
{
PostMessage(m_Window,WM_QUIT,0,0);
m_IsProgramLooping=false; //停止程序循环
}
/*消息循环*/
LRESULT GL_Application::Message(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
switch(uMsg)
{
case WM_SYSCOMMAND:
switch(wParam)
{
case SC_SCREENSAVE:
case SC_MONITORPOWER:
return 0;
break;
}
break;
case WM_CLOSE:
TerminateApplication();
return 0;
break;
case WM_EXITMENULOOP:
case WM_EXITSIZEMOVE:
m_LastTickCount=GetTickCount(); //更新计数器的值
return 0;
break;
case WM_MOVE:
m_Window.SetPosX(LOWORD(lParam)); //更新鼠标的坐标
m_Window.SetPosY(HIWORD(lParam));
return 0;
break;
case WM_PAINT:
if(m_ResizeDraw==true) //如果需要重绘
{
m_Window.ReshapeGL();
Draw();
m_Window.SwapBuffers();
}
break;
case WM_SIZING: //窗口正在改变大小
{
RECT *rect=(RECT*)lParam;
m_Window.SetWidth(rect->right-rect->left); //设置窗口宽度
m_Window.SetHeight(rect->bottom-rect->top);
return TRUE;
}
break;
case WM_SIZE: //窗口改变大小后
{
switch(wParam)
case SIZE_MINIMIZED:
m_IsVisible=false;
return 0;
break;
case SIZE_MAXIMIZED:
case SIZE_RESTORED:
m_IsVisible=true;
m_Window.SetWidth(LOWORD(lParam));
m_Window.SetHeight(HIWORD(lParam));
m_Window.ReshapeGL();
m_LastTickCount=GetTickCount();
return 0;
break;
}
break;
case WM_KEYDOWN: //更新按键信息
m_Keys.SetPressed(wParam);
return 0;
break;
case WM_KEYUP:
m_Keys.SetReleased(wParam);
return 0;
break;
case WM_TOGGLEFULLSCREEN:
m_CreateFullScreen=!m_CreateFullScreen;
PostMessage(hWnd,WM_QUIT,0,0);
break;
}
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
#endif