Structuring Your Program for Painting

The window procedure in SYSMETS2 does not repaint the client area after processing a scroll bar message. Instead, it calls InvalidateRect to invalidate the client area. This causes Windows to place a WM_PAINT message in the message queue.

It is best to structure your Windows programs so that you do all client-area painting in response to a WM_PAINT message. Because your program should be able to repaint the entire client area of the window at any time on receipt of a WM_PAINT message, you will probably duplicate code if you also paint in other parts of the program.

At first, you may rebel at this dictum because it is so different from normal PC programming. I won't deny that, on occasion, painting in response to messages other than WM_PAINT is much more convenient. (The KEYLOOK program in the next chapter is an example of such a program.) But in many cases it's simply unnecessary, and after you master the discipline of accumulating all the information you need to paint in response to a WM_PAINT message, you'll be pleased with the results. However, your program will often determine that it must repaint a particular area of the display when processing a message other than WM_PAINT. This is where InvalidateRect comes in handy. You can use it to invalidate specific rectangles of the client area or the entire client area.

Simply marking areas of the window as invalid to generate WM_PAINT messages may not be entirely satisfactory in some applications. After you make an InvalidateRect call, Windows places a WM_PAINT message in the message queue, and the window procedure eventually processes it. However, Windows treats WM_PAINT messages as low priority. If your message queue contains only a WM_PAINT message and another application has other messages waiting, Windows switches to the other application when you make a GetMessage call.

If you prefer to update the invalid area immediately, you can call UpdateWindow after you call InvalidateRect:

UpdateWindow (hwnd) ;

UpdateWindow causes the window procedure to be called immediately with a WM_PAINT message if any part of the client area is invalid. (It will not call the window procedure if the entire client area is valid.) This WM_PAINT message bypasses the message queue. The window procedure is called directly from Windows. When the window procedure has finished repainting, it exits and Windows returns control to the program at the statement following the UpdateWindow call.

You'll note that UpdateWindow is the same function used in WinMain to generate the first WM_PAINT message. When a window is first created, the entire client area is invalid. UpdateWindow directs the window procedure to paint it.