Window OpenGL 程序C++版本

程序结构有待改善,能正常运行,不足之处欢迎指出。

COpenGL.h

#ifndef _COPENGL_H
#define _COPENGL_H

#include "OpenGLFrame.h"

class COpenGL{

private:
 HDC m_hDC;       //设备描述表
 HGLRC m_hRC;      //渲染描述表
 int m_iWidth;
 int m_iHeight;

public:
 HWND m_hWnd;      //窗口句柄
 HINSTANCE m_hInstance;    //程序实例
 bool m_bFullScreen;     //是否全屏显示
 bool m_bActive;      //是否为活动窗口

 bool m_bKeyState[256];    //按键状态
 double m_fRotated;
 double m_fTranslate;
 char m_szWindowClass[32];
 char m_szTitle[32];
 int m_iBits;
 PIXELFORMATDESCRIPTOR m_pfd;

public:
 COpenGL();
 ~COpenGL();


 int InitializeGL(void);
 int CreateGLWindow(int width, int height, int bits);
 int RenderingScene(void);
 void SwapBuffers();
 int SetPixelFormat(PIXELFORMATDESCRIPTOR * pfd);
 int ChangeDisplaySettings(int width, int height, int bits);
 void KillWindow(void);
 void ResizeScene(GLsizei width, GLsizei height);
};

COpenGL.cpp

#include "COpenGL.h"

extern LRESULT CALLBACK MsgProc(HWND, UINT, WPARAM, LPARAM);

COpenGL::COpenGL()
{
 this->m_hWnd = NULL;
 this->m_hInstance = NULL;
 this->m_hDC = NULL;
 this->m_bActive = true;
 this->m_bFullScreen = true;
 this->m_iBits = 16;
 this->m_fRotated = 0.0;
 this->m_fTranslate = 0.0;
 memset(m_bKeyState, 0, sizeof(bool)*256);
 memcpy(m_szWindowClass, "OpenGL", 7);
 memcpy(m_szTitle, "OpenGL Frame", 13); 
 
 //像素格式 PIXELFORMATDESCRIPTOR
 m_pfd.nSize    = sizeof(PIXELFORMATDESCRIPTOR);
 m_pfd.nVersion   = 1;        //版本号
 m_pfd.dwFlags   = PFD_DRAW_TO_WINDOW |    //像素格式支持窗体绘制
         PFD_SUPPORT_OPENGL |    //像素格式必须支持OpenGL
         PFD_DOUBLEBUFFER;     //双缓存
 m_pfd.iPixelType  = PFD_TYPE_RGBA;     //RGBA色彩
 m_pfd.cColorBits  = this->m_iBits;     //色深
 m_pfd.cRedBits   = 0;        //忽略色彩位
 m_pfd.cRedShift   = 0;
 m_pfd.cGreenBits  = 0;
 m_pfd.cGreenShift  = 0;
 m_pfd.cBlueBits   = 0;
 m_pfd.cBlueShift  = 0;        //忽略色彩位
 m_pfd.cAlphaBits  = 0;        //无Alpha缓存
 m_pfd.cAlphaShift  = 0;        //shift bit Ignored
 m_pfd.cAccumBits  = 0;        //无累积缓存
 m_pfd.cAccumRedBits  = 0;        //忽略累积缓存位
 m_pfd.cAccumGreenBits = 0;        //
 m_pfd.cAccumBlueBits = 0;         //
 m_pfd.cAccumAlphaBits = 0;        //忽略累积缓存位
 m_pfd.cDepthBits  = 16;        //16位深度缓存
 m_pfd.cStencilBits  = 0;        //无模板缓存
 m_pfd.cAuxBuffers  = 0;        //无辅助缓存
 m_pfd.iLayerType  = PFD_MAIN_PLANE;     //主图层
 m_pfd.bReserved   = 0;        //保留位
 m_pfd.dwLayerMask  = 0;        //忽略图层掩码
 m_pfd.dwVisibleMask  = 0;        //忽略图层掩码
 m_pfd.dwDamageMask  = 0;        //忽略图层掩码
}

COpenGL::~COpenGL()
{

}

int COpenGL::CreateGLWindow(int width, int height, int bits)
{

 m_iHeight = height;
 m_iWidth = width;
m_iBits = b

 DWORD dwExStyle = 0;    //扩展窗体风格
 DWORD dwStyle = 0;     //窗体风格
 WNDCLASS wc;
 
 RECT WindowRect;
 WindowRect.left  = (long)0;
 WindowRect.top  = (long)0;
 WindowRect.right = (long)width;
 WindowRect.bottom = (long)height;

 //为窗体获取实例
 m_hInstance = ::GetModuleHandle(NULL);

 //CS_HREDRAW, CS_VREDRAW表示在横纵方向上改变窗体大小重绘窗体, CS_OWNDC表示窗体自己拥有DC
 wc.style   = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
 wc.lpfnWndProc  = (WNDPROC)MsgProc;
 wc.cbClsExtra  = 0;
 wc.cbWndExtra  = 0;
 wc.hInstance  = m_hInstance;
 wc.hCursor   = ::LoadCursor(NULL, IDC_ARROW);
 wc.hIcon   = ::LoadIcon(NULL, IDI_WINLOGO);
 wc.hbrBackground = NULL;      //OpenGL函数可以设置
 wc.lpszMenuName  = NULL;
 wc.lpszClassName = m_szWindowClass;

 if(!RegisterClass(&wc))
 {
  MessageBox(NULL, "Failed To Register The Window Class !",
     "ERROR", MB_OK | MB_ICONEXCLAMATION);
  return 0;
 }

 if(!this->ChangeDisplaySettings(width, height, bits))
  return 0;

 if(m_bFullScreen)
 {
  dwExStyle = WS_EX_APPWINDOW;
  dwStyle = WS_POPUP;      //pop up 突然出现
  ShowCursor(false);      //隐藏鼠标
 }
 else
 {
  //WS_EX_APPWINDOW最上层窗体位于任务栏上方, WS_EX_WINDOWDGE制定窗体边框突出
  dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;  
  dwStyle = WS_OVERLAPPEDWINDOW;
 }
 //根据窗体风格调整窗体大小,实际可使用客户区域被覆盖,全屏情况无效
 AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);
 //创建窗体
 m_hWnd = ::CreateWindowEx(
    dwExStyle,
    m_szWindowClass,
    m_szTitle,
    dwStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
    0, 0,        //窗体位置
    WindowRect.right-WindowRect.left,
    WindowRect.bottom-WindowRect.top,
    NULL,
    NULL,
    m_hInstance,
    NULL);
 if(NULL==m_hWnd)
 {
  this->KillWindow();
  MessageBox(NULL, "Window Creation Error !", "ERROR", MB_OK | MB_ICONEXCLAMATION);
  return 0;
 }
 
if(NULL == (m_hDC=::GetDC(m_hWnd)))
 {
  this->KillWindow();
  MessageBox(NULL, "Can't Create a GL Device Context !",
   "Error", MB_OK | MB_ICONEXCLAMATION);
  return 0;
 }

 if(!this->SetPixelFormat(&m_pfd))
  return 0;

 //将渲染描述表和设备描述表关联
 if(!(m_hRC = wglCreateContext(m_hDC)))
 {
  this->KillWindow();
  MessageBox(NULL, "Can't Create a GL Rendering Context !",
   "Error", MB_OK | MB_ICONEXCLAMATION);
  return 0;
 }
 //设置当前渲染描述表
 if(!wglMakeCurrent(m_hDC, m_hRC))
 {
  this->KillWindow();
  MessageBox(NULL, "Can't Activate The GL Rendering Context",
   "Error", MB_OK | MB_ICONEXCLAMATION);
  return 0;
 }
 //显示窗体
 ShowWindow(m_hWnd, SW_SHOW);
 SetForegroundWindow(m_hWnd);   //提高当前窗体的优先级
 SetFocus(m_hWnd);      //设置焦点窗体
 this->ResizeScene(width, height);  //设置OpenGL窗体大小
 
 if(!this->InitializeGL())
 {
  this->KillWindow();
  ::MessageBox(NULL, "Failed to Initialize the Window !",
   "Error", MB_OK | MB_ICONEXCLAMATION);
  return 0;
 }

 return 1;
}

int COpenGL::InitializeGL()
{
 glClearColor(0.0, 0.0, 0.0, 0.0);
 glClearDepth(1.0);    //深度缓存
 glShadeModel(GL_SMOOTH);  //GL_SMOOTH平滑着色,GL_FLAT恒定着色
 glEnable(GL_DEPTH_TEST);  //开启深度测试
 glDepthFunc(GL_LEQUAL);   //GL_LEQUAL 小于等于存储的Z值的定点允许渲染
 //设置细节实现的提示,控制OpenGL行为P162
 //GL_PERSPECTIVE_CORRECTION_HINT指定透视修订和颜色的插值
 //GL_NICEST指定图像质量最好
 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
 return 1;
}

void COpenGL::ResizeScene(GLsizei width, GLsizei height)
{
 if(0 == height)
  height = 1;
 glViewport(0, 0, width, height); //指定视口
 glMatrixMode(GL_PROJECTION); 
 glLoadIdentity();    //初始化投影矩阵
 //设置投影体, 为防止窗口大小改变时图形变形,第二个参数值为视口的宽高比
 gluPerspective((GLfloat)45.0, (GLfloat)width/(GLfloat)height, 
  (GLfloat)1.0, (GLfloat)100.0); 
 glMatrixMode(GL_MODELVIEW);
}

int COpenGL::RenderingScene(void)
{
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  //清空颜色缓存和深度缓存
 glLoadIdentity();   //初始化模型视点矩阵
 return 1;
}

void COpenGL::KillWindow(void)
{
 if(m_bFullScreen)
 {
  ::ChangeDisplaySettings(NULL, 0);  //返回桌面
  ShowCursor(true);     //显示鼠标
 }
 if(m_hRC) 
 {
  if(!wglMakeCurrent(NULL, NULL))  //分离RC与DC 测试是否成功分离
  {
   MessageBox(NULL, "Release of DC and RC Failed !", "Shutdown Error",
      MB_OK|MB_ICONINFORMATION);
  }
  if(!wglDeleteContext(m_hRC))   //释放RC
  {
   MessageBox(NULL, "Release Rendering Context Failed !", "Shutdown Error",
      MB_OK | MB_ICONINFORMATION);
  }
  m_hRC = NULL;
 }
 if(m_hDC && !ReleaseDC(m_hWnd, m_hDC))  //&&运算符从左到右,释放DC
 {
  MessageBox(NULL, "Release Device Context Failed !", "Shutdown Error",
     MB_OK | MB_ICONINFORMATION);
  m_hDC = NULL;
 }
 if(m_hWnd && !DestroyWindow(m_hWnd))   //销毁窗口
 {
  MessageBox(NULL, "Could Not Release hWnd !", "Shutdown Error",
     MB_OK | MB_ICONINFORMATION);
  m_hWnd = NULL;
 }

 if(!UnregisterClass(m_szWindowClass, m_hInstance))
 {
  MessageBox(NULL, "Could Not Unregister Class !", "Shutdown Error",
     MB_OK | MB_ICONINFORMATION);
  m_hInstance = NULL;
 }
}

void COpenGL::SwapBuffers()
{
  ::SwapBuffers(m_hDC);
}

int COpenGL::ChangeDisplaySettings(int width, int height, int bits)
{
 if(m_bFullScreen)
 {
  DEVMODE dmScreenSettings;
  memset(&dmScreenSettings, 0, sizeof(DEVMODE));
  dmScreenSettings.dmSize   = sizeof(DEVMODE);
  dmScreenSettings.dmBitsPerPel = bits;   //像素位数
  dmScreenSettings.dmPelsWidth = width;  //屏幕宽
  dmScreenSettings.dmPelsHeight = height;  //屏幕高
  dmScreenSettings.dmFields  = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
  if( DISP_CHANGE_SUCCESSFUL != ::ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) ) //切换显示模式
  {
   if( IDYES == MessageBox(NULL, "The Requested FullScreen Mode Is Not"
      "Supported by/nYour Video Card. Use Windowed Mode Instead?",
      "My Windows OpenGL Frame", MB_YESNO | MB_ICONEXCLAMATION) )
   {
    m_bFullScreen = false;
   }
   else
   {
    MessageBox(NULL, "Program Will Now Close", "ERROR", MB_OK | MB_ICONSTOP);
    return 0;
   }
  }
 }
 return 1;
}

int COpenGL::SetPixelFormat(PIXELFORMATDESCRIPTOR * pfd)
{
 GLuint PixelFormat = 0;
 //像素格式
 memcpy(&m_pfd, pfd, sizeof(PIXELFORMATDESCRIPTOR));
 //查找是否有合适的像素格式
 if(!(PixelFormat = ::ChoosePixelFormat(m_hDC, pfd)))
 {
  this->KillWindow();
  MessageBox(NULL, "Can't Find a Suitable Pixel Format !",
   "Error", MB_OK | MB_ICONEXCLAMATION);
  return 0;
 }
 //设置像素格式
 if(!::SetPixelFormat(m_hDC, PixelFormat, pfd))  //设置像素格式
 {
  this->KillWindow();        
  MessageBox(NULL,"Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
  return 0;        
 }
 return 1;
}


 

 

COpenGLFrame.h

#ifndef OPENGLFRAME_H
#define OPENGLFRAME_H

#include <windows.h>

#include <gl/gl.h>
#include <gl/glu.h>

#endif OPENGLFRAME_H

 

 /

COpenGLFrame.cpp

 

#include "OpenGLFrame.h"
#include "COpenGL.h"

COpenGL theOpenGL;

LRESULT CALLBACK MsgProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow)
{
 MSG msg;
 bool done = false;
 if(IDNO == MessageBox(NULL, "Would You Like To Run In Fullscreen Mode?", "Start FullScreen ?", MB_YESNO | MB_ICONQUESTION))
  theOpenGL.m_bFullScreen = false;

 if(!theOpenGL.CreateGLWindow(800, 600, 16))
  return 0;
 while(!done)
 {
  if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))  //是否有等待的消息
  {
   if(WM_QUIT == msg.message)
    done = true;
   else
   {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
   }
  }
  else
  {
   if(theOpenGL.m_bActive)
   {
    if(theOpenGL.m_bKeyState[VK_ESCAPE])       //如果ESC被按下
     done = true;
    else          //否则更新屏幕图像
    {
     theOpenGL.RenderingScene();
     theOpenGL.SwapBuffers();      //Windows SDK中双缓存交换
    }
   }
   if(theOpenGL.m_bKeyState[VK_F1])     //按F1键切换全屏模式与窗口模式
   {
    theOpenGL.m_bKeyState[VK_F1] = false;
    theOpenGL.KillWindow();      //关闭当前窗体
    theOpenGL.m_bFullScreen = !theOpenGL.m_bFullScreen;
    //切换模式重新生成窗体
    if(!theOpenGL.CreateGLWindow(800, 600, 16))
     return 0;
   }
  }
 }
 //done = true 关闭程序,退出
 theOpenGL.KillWindow();
 return (msg.wParam);
}

 

//消息处理函数
LRESULT CALLBACK MsgProc( HWND hWnd,
        UINT uMsg,
        WPARAM wParam,
        LPARAM lParam )
{
 switch(uMsg)
 {
  case WM_ACTIVATE:    //查看窗口活动状态
   if(!HIWORD(wParam))   //检查最小化情况
    theOpenGL.m_bActive = true;
   else
    theOpenGL.m_bActive = false;
   return 0;
  case WM_SYSCOMMAND:    //截取系统消息
   switch(wParam)
   {
    case SC_SCREENSAVE:  //屏幕保护启动
    case SC_MONITORPOWER: //监视器转换为节电模式
    return 0;    //组织发生
   }
   break;
  case WM_CLOSE:
   PostQuitMessage(0);
   return 0;
  case WM_KEYDOWN:    //WM_KEYDOWN, WM_KEYUP消息,wParam包含按键ASCII码
   theOpenGL.m_bKeyState[wParam] = true;  //按下键,设置该键状态为按下
   return 0;
  case WM_KEYUP:
   theOpenGL.m_bKeyState[wParam] = false;
   return 0;
  case WM_SIZE:     //WM_SIZE消息的lParam低位为窗口宽, 高位为窗口高
   theOpenGL.ResizeScene(LOWORD(lParam), HIWORD(lParam)); 
   return 0;
 }
 //处理其余消息
 return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值