The Paint Information Structure

Earlier I mentioned a ”paint information structure“ that Windows maintains for each window. That's what PAINTSTRUCT is. The structure is defined in WINDOWS.H as follows:

typedef struct tagPAINTSTRUCT

{

HDC hdc ;

BOOL fErase ;

RECT rcPaint ;

BOOL fRestore ;

BOOL fIncUpdate ;

BYTE rgbReserved[16] ;

} PAINTSTRUCT ;

Windows fills in the fields of this structure when your program calls BeginPaint. Your program may use only the first three fields. The others are used internally by Windows.

The hdc field is the handle to the device context. In a redundancy typical of Windows, the value returned from BeginPaint is also this device context handle.

In most cases, fErase will be flagged TRUE (nonzero), meaning that Windows has erased the background of the invalid rectangle. Windows erases the background using the brush specified in the hbrBackground field of the WNDCLASS structure that you use when registering the window class during WinMain initialization. Many Windows programs use a white brush:

wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;

However, if your program invalidates a rectangle of the client area by calling the Windows function InvalidateRect, one of the parameters to this function specifies whether you want the background erased. If this parameter is FALSE (or 0), then Windows will not erase the background, and the fErase field will also be FALSE.

The rcPaint field of the PAINTSTRUCT structure is a structure of type RECT. As you learned in Chapter 1, the RECT structure defines a rectangle. The four fields are left, top, right, and bottom. The rcPaint field in the PAINTSTRUCT structure defines the boundaries of the invalid rectangle, as shown in Figure 2-1. The values are in units of pixels relative to the upper left corner of the client area. The invalid rectangle is the area that you should repaint. Although a Windows program can simply repaint the entire client area of the window whenever it receives a WM_PAINT message, repainting only the area of the window defined by that rectangle saves time.

The rcPaint rectangle in PAINTSTRUCT is not only the invalid rectangle; it is also a ”clipping“ rectangle. This means that Windows restricts painting to within the clipping rectangle. When you use the device context handle from the PAINTSTRUCT structure, Windows will not paint outside the rcPaint rectangle.

To paint outside this rcPaint rectangle while processing WM_PAINT messages, you can make this call:

InvalidateRect (hWnd, NULL, TRUE) ;

before calling BeginPaint. This invalidates the entire client area and erases the background. A FALSE value in the last parameter will not erase the background, however. Whatever was there will stay.

In the HELLOWIN program in Chapter 1, we didn't care about invalid rectangles or clipping rectangles when processing the WM_PAINT message. If the area where the text was displayed happened to be within the invalid rectangle, then DrawText restored it. If not, then at some point during processing of the DrawText call, Windows determined it didn't have to write anything to the display. But this determination takes time. A programmer concerned about performance and speed will want to use the invalid-rectangle dimensions during processing of WM_PAINT to avoid unnecessary GDI calls.