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