Open GL Super Bible

Previous Table of Contents Next


Return of the Bouncing Square

At last we have enough information to create a Windows window that uses OpenGL, without using the AUX library. The program shown in Listing 4-2 contains the necessary Windows code along with the rendering function from Chapter 3ís BOUNCE2 example program. You can see by the length of this code that the AUX library saves you a lot of effort.

The RenderScene, ChangeSize, and IdleFunction functions are virtually unchanged from the Chapter 3 example and are thus omitted here. These functions, along with the function in Listing 4-1, make up the sample program GLRECT. Figure 4-3 shows the familiar bouncing rectangle. Listing 4-2 shows the WinMain function that creates the window and services messages for the program and the WndProc function for the window that handles the individual messages.


Figure 4-3  Windows version of the bouncing square

Listing 4-2 Animated square program, without the AUX library

// Entry point of all Windows programs
int APIENTRY WinMain(  HINSTANCE       hInstance,
                       HINSTANCE       hPrevInstance,
                       LPSTR           lpCmdLine,
                       int             nCmdShow)
        {
        MSG            msg;            // Windows message structure
        WNDCLASS       wc;             // Windows class structure
        HWND           hWnd;           // Storage for window handle

        // Register Window style
        wc.style               = CS_HREDRAW | CS_VREDRAW;
        wc.lpfnWndProc         = (WNDPROC) WndProc;
        wc.cbClsExtra          = 0;
        wc.cbWndExtra          = 0;
        wc.hInstance           = hInstance;
        wc.hIcon               = NULL;
        wc.hCursor             = LoadCursor(NULL, IDC_ARROW);

        // No need for background brush for OpenGL window
        wc.hbrBackground       = NULL;          

        wc.lpszMenuName        = NULL;
        wc.lpszClassName       = lpszAppName;

        // Register the window class
        if(RegisterClass(&wc) == 0)
                return FALSE;

        // Create the main application window
        hWnd = CreateWindow(
                       lpszAppName,
                       lpszAppName,

                       // OpenGL requires WS_CLIPCHILDREN and
                       WS_CLIPSIBLINGS

                       WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN
                       | WS_CLIPSIBLINGS,

                       // Window position and size
                       100, 100,
                       250, 250,

                       NULL,
                       NULL,
                       hInstance,
                       NULL);
        // If window was not created, quit
        if(hWnd == NULL)
                return FALSE;

        // Display the window
        ShowWindow(hWnd,SW_SHOW);
        UpdateWindow(hWnd);

        // Process application messages until the application closes
        while( GetMessage(&msg, NULL, 0, 0))
                {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
                }

        return msg.wParam;
        }

// Window procedure, handles all messages for this program
LRESULT CALLBACK WndProc(      HWND    hWnd,
                               UINT    message,
                               WPARAM  wParam,
                               LPARAM  lParam)
        {
        static HGLRC hRC;              // Permanent Rendering context
        static HDC hDC;                // Private GDI Device context

        switch (message)
                  {
                  // Window creation, setup for OpenGL
                  case WM_CREATE:
                          // Store the device context
                          hDC = GetDC(hWnd);          

                          // Select the pixel format
                          SetDCPixelFormat(hDC);          

                          // Create the rendering context
                          and make it current

                          hRC = wglCreateContext(hDC);
                          wglMakeCurrent(hDC, hRC);

                          // Create a timer that fires every millisecond
                          SetTimer(hWnd,101,1,NULL);
                          break;

        // Window is being destroyed, cleanup
        case WM_DESTROY:
                // Kill the timer that we created
                KillTimer(hWnd,101);

                // Deselect the current rendering
                context and delete it

                wglMakeCurrent(hDC,NULL);
                wglDeleteContext(hRC);

                // Tell the application to terminate
               after the window

                // is gone.
                PostQuitMessage(0);
                break;

        // Window is resized.
        case WM_SIZE:
                // Call our function which modifies the clipping
                // volume and viewport
                ChangeSize(LOWORD(lParam), HIWORD(lParam));
                break;

        // Timer, moves and bounces the rectangle, simply calls
        // our previous OnIdle function, then invalidates the
        // window so it will be redrawn.
        case WM_TIMER:
                {
                IdleFunction();

                InvalidateRect(hWnd,NULL,FALSE);
                }
                break;

        // The painting function. This message sent by Windows
        // whenever the screen needs updating.
        case WM_PAINT:
                {
                // Call OpenGL drawing code
                RenderScene();

               // Call function to swap the buffers
                SwapBuffers(hDC);

               // Validate the newly painted client area
               ValidateRect(hWnd,NULL);
               }
               break;

       default:   // Passes it on if unproccessed
    return (DefWindowProc(hWnd, message, wParam, lParam));

       }
return (0L);
}

The code for the Windows version of the bouncing square will be quite understandable to you if youíve been following our discussion. Letís look at a few points that may be of special interest.


Previous Table of Contents Next