Figure 2: Implementations of classes COpenGLCtrl and COpenGLCtrls
// File OGLCtrl.cpp #include "stdafx.h" #include "OGLCtrl.h" COpenGLCtrl::COpenGLCtrl() :m_hRC(NULL),m_hDC(NULL) { RegisterOpenGLWindowClass(); } BOOL COpenGLCtrl::PreCreateWindow(CREATESTRUCT& cs) { cs.style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN; return CWnd::PreCreateWindow(cs); } void COpenGLCtrl::PreSubclassWindow() { ModifyStyle(0,WS_CLIPSIBLINGS|WS_CLIPCHILDREN); ASSERT((GetClassLong(m_hWnd,GCL_STYLE)&CS_PARENTDC)==0); InitializeOpenGLWindow(); CRect Rect; GetClientRect(&Rect); // If we are subclassing an existing window // we might have missed the WM_SIZE message if (!Rect.IsRectEmpty()) ResizeOpenGLWindow(Rect.Width(),Rect.Height()); CWnd::PreSubclassWindow(); } void COpenGLCtrl::OnSize(UINT nType, int cx, int cy) { CWnd::OnSize(nType, cx, cy); if (cx>0 && cy>0) ResizeOpenGLWindow(cx,cy); } void COpenGLCtrl::OnPaint() { CPaintDC DC(this); RedrawOpenGLWindow(); } BOOL COpenGLCtrl::OnEraseBkgnd(CDC* pDC) { return TRUE; // Don't clear background, OpenGL will } void COpenGLCtrl::OnDestroy() { UninitializeOpenGLWindow(); CWnd::OnDestroy(); } void COpenGLCtrl::SetupPixelFormat(HDC hDC) { PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR),// size of this pfd 1, // version number PFD_DRAW_TO_WINDOW // support window | PFD_SUPPORT_OPENGL // support OpenGL | PFD_DOUBLEBUFFER // double buffered , PFD_TYPE_RGBA, // RGBA type 24, // 24-bit 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, // accum bits ignored 32, // 32-bit z-buffer 0, // no stencil buffer 0, // no auxiliary buffer PFD_MAIN_PLANE, // main layer 0, // reserved 0, 0, 0 // layer masks ignored }; // Let user change the pfd structure CustomizePixelFormat(&pfd); // Set the pixel format int pixelformat=ChoosePixelFormat(hDC, &pfd); SetPixelFormat(hDC,pixelformat,&pfd); } void COpenGLCtrl::InitializeOpenGLWindow() { // Get the DC and set its pixel format m_hDC=::GetDC(m_hWnd); SetupPixelFormat(m_hDC); // Create the Rendering Context and make it current m_hRC=wglCreateContext(m_hDC); wglMakeCurrent(m_hDC,m_hRC); // Let user do his one-time initialization OnPrepareRC(); } void COpenGLCtrl::UninitializeOpenGLWindow() { // Delete the RC if (m_hRC) { OnDestroyRC(); // Let derived classes clean up wglMakeCurrent(NULL,NULL); wglDeleteContext(m_hRC); m_hRC=NULL; } // Release the DC if (m_hDC) { ::ReleaseDC(m_hWnd,m_hDC); m_hDC=NULL; } } void COpenGLCtrl::ResizeOpenGLWindow(int cx, int cy) { // Let user set his viewport transformation OnViewport(cx, cy); // Select Projection matrix and initialize it glMatrixMode(GL_PROJECTION); glLoadIdentity(); // Get the aspect ratio and set perspective transform GLdouble AspectRatio=(GLdouble)cx/(GLdouble)cy; OnProjection(AspectRatio); // Select ModelView matrix and initialize it glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // Let user set his viewing transformation OnViewing(); } void COpenGLCtrl::RedrawOpenGLWindow() { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glPushMatrix(); OnRender(); // Draw your scene glPopMatrix(); glFinish(); SwapBuffers(m_hDC); } //... Other members implement the default scene //================================================== COpenGLCtrls::COpenGLCtrls() { } void COpenGLCtrls::InitializeOpenGLWindow() { COpenGLCtrl::InitializeOpenGLWindow(); wglMakeCurrent(NULL,NULL); ::ReleaseDC(m_hWnd,m_hDC); m_hDC=NULL; } void COpenGLCtrls::UninitializeOpenGLWindow() { m_hDC=::GetDC(m_hWnd); wglMakeCurrent(m_hDC,m_hRC); COpenGLCtrl::UninitializeOpenGLWindow(); } void COpenGLCtrls::BeginOpenGLDrawing() { m_hDC=::GetDC(m_hWnd); wglMakeCurrent(m_hDC,m_hRC); } void COpenGLCtrls::EndOpenGLDrawing() { wglMakeCurrent(NULL,NULL); ::ReleaseDC(m_hWnd,m_hDC); m_hDC=NULL; } void COpenGLCtrls::ResizeOpenGLWindow(int cx, int cy) { BeginOpenGLDrawing(); COpenGLCtrl::ResizeOpenGLWindow(cx,cy); EndOpenGLDrawing(); } void COpenGLCtrls::RedrawOpenGLWindow() { BeginOpenGLDrawing(); COpenGLCtrl::RedrawOpenGLWindow(); EndOpenGLDrawing(); } //End of File