Open GL Super Bible

Previous Table of Contents Next


Get TWindowView Ready for OpenGL

AppExpert generates a class, TOwlglWindowView, derived directly from TWindowView. This class is responsible for the client window area of the application. In our example, that class is declared in the file owlglwnv.h and implemented in the file owlglwnv.cpp.

Now we fill in the code for the WM_CREATE handler. As noted earlier in this Chapter, the first requirement of any window that will be used for OpenGL is that the window styles WS_CLIPCHILDREN and WS_CLIPSIBLINGS are set when the window is created. Since we have already set these styles in the AppExpert before generating this program, we donít need to do anything further for this requirement. However, should you need to set this programatically, you can do it easily in the WM_CREATE handler, as follows:

int TOwlglWindowView::EvCreate(CREATESTRUCT& cs)
        {
        int result;

        // Add Styles for OpenGL windows
        cs.style |= (WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CS_OWNDC);
        result = TWindowView::EvCreate(cs);
         ...
         ...

Notice that we also set the style for CS_OWNDC, so the window can have its own private device context. Although this is not strictly necessary, it saves time and works better with OWL. Some device context pointers returned by OWL functions are temporary and cannot be stored for later use (this is also true for MFC, by the way). So itís better to get it once and keep it.

Space in the TOwlglWindowView class is allocated to store the device context, the rendering context, and the palette, with the following code from owlglwnv.h:

public:
        HGLRC m_hRC;                     // Rendering context
        HDC m_hDC = NULL;                // Device context
        TPalette *m_pPalette;            // 3-3-2 Palette

Pixel Format and Rendering Context

In the remainder of our WM_CREATE handler, we will set the pixel format and create a rendering context for the window. Since the device context is required to create a pixel format, weíll wait to do this until after the window is created. Setting the Pixel Format within the WM_CREATE handler is done the same way as for any of the C program examples presented in this book after Chapter 3 (remember we ditched the AUX library after this). Listing 22-1 shows our finished message handler, with the code that selects the pixel format for the device context.

Listing 22-1 WM_CREATE message handler that sets the pixel format

// Handles WM_CREATE message
int TOwlglWindowView::EvCreate(CREATESTRUCT far& createStruct)
{
  int result;

  createStruct.style |= (WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CS_OWNDC);

  result = TWindowView::EvCreate(createStruct);

    // Select pixel format/rendering context
    static PIXELFORMATDESCRIPTOR pfd = {
          sizeof(PIXELFORMATDESCRIPTOR), // Size of this structure
          1,                             // Version of this structure
          PFD_DRAW_TO_WINDOW |           // Draw to window (not to bitmap)
          PFD_SUPPORT_OPENGL |           // Support OpenGL calls in window
          PFD_DOUBLEBUFFER,              // Double-buffered mode
          PFD_TYPE_RGBA,                 // RGBA color mode
          24,                            // Want 24-bit color
          0,0,0,0,0,0,                   // Not used to select mode
          0,0,                           // Not used to select mode
          0,0,0,0,0,                     // Not used to select mode
          32,                            // Size of depth buffer
          0,                             // Not used to select mode
          0,                             // Not used to select mode
          PFD_MAIN_PLANE,                // Draw in main plane
          0,                             // Not used to select mode
          0,0,0 };                       // Not used to select mode
    // Get the device context
    m_hDC = ::GetDC(this->GetHandle());

    // Choose a pixel format that best matches that described in pfd
    int nPixelFormat = ChoosePixelFormat(m_hDC, &pfd);

    // Set the pixel format for the device context
    SetPixelFormat(m_hDC, nPixelFormat, &pfd);

    // Create a 3-3-2 palette
    SetupPalette(m_hDC);

    // Create the rendering context
    m_hRC = wglCreateContext(m_hDC);

    // Make the rendering context current and perform initializion.
    wglMakeCurrent(m_hDC,m_hRC);
    GLSetupRC(m_hDC);

  // Set a timer for 200 milliseconds
  SetTimer(200,101,NULL);

  return result;
}

Immediately after creating the rendering context, we make it current and call the external function GLSetupRC(). This function will do any initialization we need for the rendering context, after which we make it not current.This allows us to use more than one rendering context in case we need multiple windows that use OpenGL. (We wonít for our sample, but if you build on this, itís wise to have the option for more than one OpenGL window without the need to recode what you already have.)

Clean Up the Rendering Context

We should go ahead and add the code to clean up and delete the rendering context before we forget. We do this in the WM_DESTROY handler, as shown in Listing 22-2.

Listing 22-2 WM_DESTROY handler cleans up rendering context

// Handles WM_DESTROY message
void TOwlglWindowView::EvDestroy()
{
// Kill the timer
KillTimer(101);

        // Free the rendering context
        wglMakeCurrent(NULL,NULL);
        wglDeleteContext(m_hRC);

        // Release the device context
        ::ReleaseDC(this->GetHandle(),m_hDC);

        TWindowView::EvDestroy();
}


Previous Table of Contents Next