Open GL Super Bible

Previous Table of Contents Next


Scaling to the Window

In our AUX library-based example in Chapter 3, the AUX library called the registered function ChangeSize whenever the window dimension changed. For our new example, we need to trap the WM_SIZE message sent by Windows when the call to ChangeSize occurs. Now we call ChangeSize ourselves, passing the LOWORD of lParam, which represents the new width of the window, and the HIWORD of lParam, which contains the new height of the window.

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

Ticktock, the Idle Clock

Also handled graciously for us by the AUX library was a call to our function IdleFunction. This function was called whenever the program didn’t have anything better to do (such as draw the scene). We can easily simulate this activity by setting up a Windows timer for our window. The following code:

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

which is called when the window is created, sets up a Windows timer for the window. A WM_TIMER message is sent every millisecond by Windows to the OpenGL window. Actually, this happens as often as Windows can send the messages—no less than a millisecond apart—and only when there are no other messages in the applications message queue. (See the Windows API Bible, by James L. Conger, published by Waite Group Press for more information on Windows timers.) When the WndProc function receives a WM_TIMER message, this code is executed:

case WM_TIMER:
        {
        IdleFunction(); 
        
        InvalidateRect(hWnd,NULL,FALSE);
        }
        break;

The IdleFunction is identical to the version in BOUNCE2 except that now it doesn’t contain a call to RenderScene(). Instead, the window is repainted by calling InvalidateRect, which causes Windows to post a WM_PAINT message.

Lights, Camera, Action!

Everything else is in place, and now it’s time for action. The OpenGL code to render the scene is placed within the WM_PAINT message handler. This code calls RenderScene (again, stolen from the BOUNCE2 example), swaps the buffers, and validates the window (to keep further WM_PAINT messages from coming).

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;

Here we also find a new function for the Windows GDI, SwapBuffers. This function serves the same purpose the auxSwapBuffers—to move the back buffer of a double-buffered window to the front. The only parameter is the device context. Note that this device context must have a pixel format with the PFD_DOUBLEBUFFER flag set; otherwise, the function fails.

That’s it! You now have a code skeleton into which you can drop any OpenGL rendering procedure you want. It will be neatly maintained in a window that has all the usual Windows properties (moving, resizing, and so on). Furthermore, you can of course use this code to create an OpenGL window as part of a full-fledged application that includes other windows, menus, and so on.


Missing Palette Code
If you compare the code from the GLRECT program listing here with the one on the CD, you will notice two other windows messages that are handled by that code but not by the code listed here. These two messages, WM_QUERYNEWPALETTE and WM_PALETTECHANGED, handle Windows palette mapping. Another function, GetOpenGLPalette, creates the palette for us. Palettes are a necessary evil when using a graphics card that supports only 256 or fewer colors. Without this code, we could not get the colors we asked for with glColor, nor even a close approximation when using these particular cards. Palettes and color under Windows constitute a significant topic that is covered in Chapter 8, where we give it the attention it deserves. This is yet another dirty detail that the AUX library hid from us!

Summary

In this chapter you should have gained an appreciation for all the work that goes on behind the scenes when you use the AUX library for your program and window framework. You’ve seen how the concept of rendering contexts was introduced to the Windows GDI so that OpenGL would know which window into which it was allowed to render. You have also learned how selecting and setting a pixel format prepares the device context before a rendering context can be created for it. In addition, you have seen which Windows messages should be processed to provide the functionality of the AUX library helper functions for window resizing and idle-time animation.

The following Reference Section contains some additional functions not covered in this chapter’s discussion because their use requires some concepts and functionality not yet introduced. You’ll find examples of these functions on the CD, demonstrating all the functions in our References. You are encouraged to explore and modify these examples.


Previous Table of Contents Next