今天写了个基于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;
}