基于MFC对话框的OpenGL类

类别:VC语言 点击:0 评论:0 推荐:

  今天写了个基于MFC对话框的OpenGL类:COpenGL,可以在对话框程序中使用OpenGL了,并且提供了全屏与非全屏转换的两个函数,很容易使用,速度快。  可以到这里下载demo project。有什么意见或问题,请大家给我留言。:)
  使用方法:在对话框上加一个Static控件(或者其他的也可以),在OnInitDialog()中加人下面这段代码(假设控件ID为IDC_OPENGL,m_openGL是类COpenGL的对象):

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

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

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

codeDivStart() #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_) codeDivEnd()


codeDivStart() // 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;
}

codeDivEnd()



本文地址:http://com.8s8s.com/it/it188.htm