明辉手游网中心:是一个免费提供流行视频软件教程、在线学习分享的学习平台!

制作一个基于MFC对话框的OpenGL类

[摘要]今天写了个基于MFC对话框的OpenGL类:COpenGL,可以在对话框程序中使用OpenGL了,并且提供了全屏与非全屏转换的两个函数,很容易使用,速度快。  使用方法:在对话框上加一个Static控件(或者其他的也可以),在OnInitDialog()中加人下面这段代码(假设控件ID为IDC_O...
今天写了个基于MFC对话框的OpenGL类:COpenGL,可以在对话框程序中使用OpenGL了,并且提供了全屏与非全屏转换的两个函数,很容易使用,速度快。

  使用方法:在对话框上加一个Static控件(或者其他的也可以),在OnInitDialog()中加人下面这段代码(假设控件ID为IDC_OPENGL,m_openGL是类COpenGL的对象):

Code: CRect rect;
GetDlgItem(IDC_OPENGL)->GetWindowRect(rect);
ScreenToClient(rect);
m_openGL.Create(rect, this);

  然后在适当的地方调用m_openGL.RenderGLScene()就可以了。

  以下是类代码(OpenGL.h和OpenGL.cpp):

Code:#if !defined(AFX_OPENGL_H__38B5D1C8_2DFF_4A7D_9A99_3AC401C19D72__INCLUDED_)
#define AFX_OPENGL_H__38B5D1C8_2DFF_4A7D_9A99_3AC401C19D72__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// OpenGL.h : header file
//

/////////////////////////////////////////////////////////////////////////////
// COpenGL window

class COpenGL : public CWnd
{
 // Construction
 public:
  COpenGL();
 
  // Attributes
 public:

  // Operations
 public:

  // Overrides
  // ClassWizard generated virtual function overrides
  //{{AFX_VIRTUAL(COpenGL)
  //}}AFX_VIRTUAL

  // Implementation
 public:
  BOOL SetNormScreen();
  BOOL SetFullScreen(int width, int height, int depth);
  virtual void RenderGLScene();
  void Create(CRect rect, CWnd *parent);
  virtual ~COpenGL();

  // Generated message map functions
 protected:
  CRect m_rect;
  CWnd* m_parent;
  BOOL m_bFullScreen;
  DEVMODE m_DMsaved;
  BOOL m_bInit;
  int InitGL();
  void KillGLWindow();
  HDC m_hDC;
  HGLRC m_hRC;
  //{{AFX_MSG(COpenGL)
  afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
  afx_msg void OnPaint();
  afx_msg void OnSize(UINT nType, int cx, int cy);
 //}}AFX_MSG
 DECLARE_MESSAGE_MAP()
};

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_OPENGL_H__38B5D1C8_2DFF_4A7D_9A99_3AC401C19D72__INCLUDED_)

Code:// OpenGL.cpp : implementation file
//

#include "stdafx.h"
#include "DialogOpenGL.h"
#include "OpenGL.h"
#include <gl/gl.h>
#include <gl/glu.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// COpenGL

COpenGL::COpenGL():m_bInit(FALSE),m_bFullScreen(FALSE),
m_hDC(NULL),m_hRC(NULL),m_parent(NULL)
{
}

COpenGL::~COpenGL()
{
 KillGLWindow(); // Shutdown
}


BEGIN_MESSAGE_MAP(COpenGL, CWnd)
 //{{AFX_MSG_MAP(COpenGL)
  ON_WM_CREATE()
  ON_WM_PAINT()
  ON_WM_SIZE()
  ON_WM_KEYDOWN()
 //}}AFX_MSG_MAP
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// COpenGL message handlers

void COpenGL::Create(CRect rect, CWnd *parent)
{
 if (m_bInit) return;
 ASSERT(rect);
 ASSERT(parent);
 m_rect = rect;
 m_parent = parent;

 CString className = AfxRegisterWndClass(
  CS_HREDRAW CS_VREDRAW CS_OWNDC,NULL,(HBRUSH)GetStockObject(BLACK_BRUSH),NULL);

  CreateEx(0,className,"OpenGL",WS_CHILD WS_VISIBLE WS_CLIPSIBLINGS WS_CLIPCHILDREN,rect,parent,0);
 }

 int COpenGL::OnCreate(LPCREATESTRUCT lpCreateStruct)
 {
  if (CWnd::OnCreate(lpCreateStruct) == -1)
   return -1;

  // TODO: Add your specialized creation code here
  EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &m_DMsaved);

  GLuint PixelFormat; // Holds The Results After Searching For A Match
  static PIXELFORMATDESCRIPTOR pfd= // pfd Tells Windows How We Want Things To Be
  {
   sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
   1, // Version Number
   PFD_DRAW_TO_WINDOW // Format Must Support Window
   PFD_SUPPORT_OPENGL // Format Must Support OpenGL
   PFD_DOUBLEBUFFER, // Must Support Double Buffering
   PFD_TYPE_RGBA, // Request An RGBA Format
   m_DMsaved.dmBitsPerPel, // Select Our Color Depth
   0, 0, 0, 0, 0, 0, // Color Bits Ignored
   0, // No Alpha Buffer
   0, // Shift Bit Ignored
   0, // No Accumulation Buffer
   0, 0, 0, 0, // Accumulation Bits Ignored
   16, // 16Bit Z-Buffer (Depth Buffer)
   0, // No Stencil Buffer
   0, // No Auxiliary Buffer
   PFD_MAIN_PLANE, // Main Drawing Layer
   0, // Reserved
   0, 0, 0 // Layer Masks Ignored
  };

  if ( !( m_hDC = ::GetDC ( m_hWnd ) ) ) { // Did We Get A Device Context?
   KillGLWindow (); // Reset The Display
   TRACE ( "Can't Create A GL Device Context." );
   return FALSE;
  }

  if ( !( PixelFormat = ChoosePixelFormat ( m_hDC, &pfd ) ) ) { // Did Windows Find A Matching Pixel Format?
   KillGLWindow (); // Reset The Display
   TRACE ( "Can't Find A Suitable PixelFormat." );
   return FALSE;
  }

  if ( !SetPixelFormat ( m_hDC, PixelFormat, &pfd ) ){ // Are We Able To Set The Pixel Format?
   KillGLWindow (); // Reset The Display
   TRACE ( "Can't Set The PixelFormat." );
   return FALSE;
  }

  if ( !( m_hRC = wglCreateContext ( m_hDC ) ) ) { // Are We Able To Get A Rendering Context?
   KillGLWindow (); // Reset The Display
   TRACE( " Can't Create A GL Rendering Context." );
   return FALSE;
  }

  if ( !wglMakeCurrent ( m_hDC, m_hRC ) ) { // Try To Activate The Rendering Context
   KillGLWindow (); // Reset The Display
   TRACE ( "Can't Activate The GL Rendering Context." );
   return FALSE;
  } 

  if ( !InitGL () ) { // Initialize Our Newly Created GL Window
   KillGLWindow (); // Reset The Display
   TRACE ( "Initialization Failed." );
   return FALSE;
  }
  m_bInit = TRUE;
  return 0;
 }

 void COpenGL::KillGLWindow()
 {
  if (m_bFullScreen) // Are We In Fullscreen Mode?
  {
   if (!ChangeDisplaySettings(NULL,CDS_TEST)) { // if the shortcut doesn't work
    ChangeDisplaySettings(NULL,CDS_RESET); // Do it anyway (to get the values out of the registry)
    ChangeDisplaySettings(&m_DMsaved,CDS_RESET); // change it to the saved settings
   } else {
    ChangeDisplaySettings(NULL,CDS_RESET);
   }

   ShowCursor(TRUE); // Show Mouse Pointer
  }

  if ( m_hRC ) { // Do We Have A Rendering Context?
   if ( !wglMakeCurrent ( NULL, NULL ) ) { // Are We Able To Release The DC And RC Contexts?
    TRACE ( "Release Of DC And RC Failed." );
   }

   if ( !wglDeleteContext ( m_hRC ) ) { // Are We Able To Delete The RC?
    TRACE ( "Release Rendering Context Failed." );
   }
   m_hRC = NULL; // Set RC To NULL
  }

  if ( m_hDC && !::ReleaseDC ( m_hWnd, m_hDC ) ) { // Are We Able To Release The DC
   TRACE ( "Release Device Context Failed." );
   m_hDC = NULL; // Set DC To NULL
  }

  if ( m_hWnd && !::DestroyWindow ( m_hWnd ) ) { // Are We Able To Destroy The Window?
   TRACE( "Could Not Release m_hWnd." );
   m_hWnd = NULL; // Set m_hWnd To NULL
  }
 }

 int COpenGL::InitGL()
 {
  glShadeModel(GL_SMOOTH); // Enable Smooth Shading
  glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background
  glClearDepth(1.0f); // Depth Buffer Setup
  glEnable(GL_DEPTH_TEST); // Enables Depth Testing
  glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do
  glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations
  glEnable(GL_TEXTURE_2D); // Enable Texture Mapping

  return TRUE; // Initialization Went OK
 }

 void COpenGL::RenderGLScene()
 {
  if(!m_bInit) return;

  glClear(GL_COLOR_BUFFER_BIT GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer
  glLoadIdentity();

  // EXAMPLE OPENGL CODE START ////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////////////////////
  static GLfloat xrot; // X Rotation
  static GLfloat yrot; // Y Rotation
  static GLfloat zrot; // Z Rotation

  glPushMatrix(); // Push Matrix Onto Stack (Copy The Current Matrix)
  glLoadIdentity(); // Reset The Current Modelview Matrix
  glTranslatef(0.0f,0.0f,-6.0f); // Move Left 1.5 Units And Into The Screen 6.0

  glRotatef(xrot,1.0f,0.0f,0.0f);
  glRotatef(yrot,0.0f,1.0f,0.0f);
  glRotatef(zrot,0.0f,0.0f,1.0f);

  glBegin(GL_QUADS);
  // Front Face
  glColor3f(1.0f,0.0f,0.0f);glVertex3f(-1.0f, -1.0f, 1.0f);
  glColor3f(0.0f,1.0f,0.0f);glVertex3f( 1.0f, -1.0f, 1.0f);
  glColor3f(0.0f,1.0f,0.0f);glVertex3f( 1.0f, 1.0f, 1.0f);
  glColor3f(0.0f,0.0f,1.0f);glVertex3f(-1.0f, 1.0f, 1.0f);
  // Back Face
  glColor3f(1.0f,0.0f,0.0f);glVertex3f(-1.0f, -1.0f, -1.0f);
  glColor3f(0.0f,1.0f,0.0f);glVertex3f(-1.0f, 1.0f, -1.0f);
  glColor3f(0.0f,1.0f,0.0f);glVertex3f( 1.0f, 1.0f, -1.0f);
  glColor3f(0.0f,0.0f,1.0f);glVertex3f( 1.0f, -1.0f, -1.0f);
  // Top Face
  glColor3f(0.0f,1.0f,0.0f);glVertex3f(-1.0f, 1.0f, -1.0f);
  glColor3f(0.0f,0.0f,1.0f);glVertex3f(-1.0f, 1.0f, 1.0f);
  glColor3f(0.0f,1.0f,0.0f);glVertex3f( 1.0f, 1.0f, 1.0f);
  glColor3f(0.0f,1.0f,0.0f);glVertex3f( 1.0f, 1.0f, -1.0f);
  // Bottom Face
  glColor3f(1.0f,0.0f,0.0f);glVertex3f(-1.0f, -1.0f, -1.0f);
  glColor3f(0.0f,0.0f,1.0f);glVertex3f( 1.0f, -1.0f, -1.0f);
  glColor3f(0.0f,1.0f,0.0f);glVertex3f( 1.0f, -1.0f, 1.0f);
  glColor3f(1.0f,0.0f,0.0f);glVertex3f(-1.0f, -1.0f, 1.0f);
  // Right face
  glColor3f(0.0f,0.0f,1.0f);glVertex3f( 1.0f, -1.0f, -1.0f);
  glColor3f(0.0f,1.0f,0.0f);glVertex3f( 1.0f, 1.0f, -1.0f);
  glColor3f(0.0f,1.0f,0.0f);glVertex3f( 1.0f, 1.0f, 1.0f);
  glColor3f(0.0f,1.0f,0.0f);glVertex3f( 1.0f, -1.0f, 1.0f);
  // Left Face
  glColor3f(1.0f,0.0f,0.0f);glVertex3f(-1.0f, -1.0f, -1.0f);
  glColor3f(1.0f,0.0f,0.0f);glVertex3f(-1.0f, -1.0f, 1.0f);
  glColor3f(0.0f,0.0f,1.0f);glVertex3f(-1.0f, 1.0f, 1.0f);
  glColor3f(0.0f,1.0f,0.0f);glVertex3f(-1.0f, 1.0f, -1.0f);

  glEnd();
  glPopMatrix(); // Pop Matrix Off The Stack

  xrot+=1.3f;
  yrot+=1.2f;
  zrot+=1.4f; // Decrease The Rotation Variable For The Quad
  //////////////////////////////////////////////////////////////////////////////
  // EXAMPLE OPENGL CODE END //////////////////////////////////////////////////////////

  // Swap our scene to the front

  SwapBuffers(m_hDC);

  Invalidate(FALSE);
 }

 void COpenGL::OnPaint()
 {
  CPaintDC dc(this); // device context for painting
 
  // TODO: Add your message handler code here
  ::ValidateRect ( m_hWnd, NULL );

  // Do not call CWnd::OnPaint() for painting messages
 }

 void COpenGL::OnSize(UINT nType, int cx, int cy)
 {
  CWnd::OnSize(nType, cx, cy);

  // TODO: Add your message handler code here
  if ( cy==0) { // Prevent A Divide By Zero By
   cy=1; // Making Height Equal One
  }

  glViewport(0,0,cx,cy); // Reset The Current Viewport

  glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
  glLoadIdentity(); // Reset The Projection Matrix

  gluPerspective(45.0f,(GLfloat)cx/(GLfloat)cy,0.1f,100.0f); // Calculate The Aspect Ratio Of The Window

  glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
  glLoadIdentity(); // Reset The Modelview Matrix

 }

 BOOL COpenGL::SetFullScreen(int width, int height, int depth)
 {
  if(!m_bInit) return FALSE;
  if (m_bFullScreen) return TRUE;

  DEVMODE dmScreenSettings; // Device Mode
  memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); // Makes Sure Memory's Cleared
  dmScreenSettings.dmSize=sizeof(dmScreenSettings); // Size Of The Devmode Structure
  dmScreenSettings.dmPelsWidth = width; // Selected Screen Width
  dmScreenSettings.dmPelsHeight = height; // Selected Screen Height
  dmScreenSettings.dmBitsPerPel = depth; // Selected Bits Per Pixel
  dmScreenSettings.dmFields=DM_BITSPERPEL DM_PELSWIDTH DM_PELSHEIGHT;

  // Try To Set Selected Mode And Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar.

  if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
  {
   return m_bFullScreen = FALSE;
  }

  SetParent(NULL);
  SetWindowPos(&CWnd::wndTop,0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), SWP_SHOWWINDOW);

  ShowCursor(FALSE);
  SetFocus();
  return m_bFullScreen = TRUE;
 }

 BOOL COpenGL::SetNormScreen()
 {
  if(!m_bInit) return FALSE;

  if (m_bFullScreen) // Are We In Fullscreen Mode?
  {
   if (!ChangeDisplaySettings(NULL,CDS_TEST)) { // if the shortcut doesn't work
    ChangeDisplaySettings(NULL,CDS_RESET); // Do it anyway (to get the values out of the registry)
    ChangeDisplaySettings(&m_DMsaved,CDS_RESET); // change it to the saved settings
   } else {
    ChangeDisplaySettings(NULL,CDS_RESET);
   }
   SetParent(m_parent);
   SetWindowPos(&CWnd::wndTop,m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(), SWP_SHOWWINDOW);
   ShowCursor(TRUE); // Show Mouse Pointer
   m_bFullScreen = FALSE;
  }
 return TRUE;