The WM_PAINT Message

The first message that WndProc processes is WM_PAINT. This message is extremely important in Windows programming. It informs a program when part or all of the window's client area is ”invalid“ and must be repainted.

How does a client area become invalid? When the window is first created, the entire client area is invalid because the program has not yet drawn anything on the window. The first WM_PAINT message (which normally occurs when the program calls UpdateWindow in WinMain) directs the window procedure to draw something on the client area.

When you resize HELLOWIN's window, the client area also becomes invalid. You'll recall that the style parameter of HELLOWIN's wndclass structure was set to the flags CS_HREDRAW and CS_VREDRAW. This directs Windows to invalidate the whole window when the size changes. The window procedure receives a WM_PAINT message.

When you minimize HELLOWIN to be displayed as an icon and then restore the window again to its previous size, Windows does not save the contents of the client area. Under a graphical environment, this would be too much data. Instead, Windows invalidates the window. The window procedure receives a WM_PAINT message and itself restores the contents of its window.

When you move windows around so they overlap, Windows does not save the area of a window covered by another window. When that area of the window is later uncovered, it is flagged as invalid. The window procedure receives a WM_PAINT message to repaint the contents of the window.

Before sending the window procedure a WM_PAINT message, Windows erases the background of the invalid area using the brush specified in the hbrBackground field of the WNDCLASS structure used to register the window class. In the case of HELLOWIN, this is a stock white brush, which means that Windows erases the background of the window by coloring it white.

WM_PAINT processing almost always begins with a call to BeginPaint:

hdc = BeginPaint (hwnd, &ps) ;

and ends with a call to EndPaint:

EndPaint (hwnd, &ps) ;

In both cases, the first parameter is a handle to the program's window and the second parameter is a pointer to a structure of type PAINTSTRUCT. PAINTSTRUCT contains some information that a window procedure can use for painting the client area. (I'll discuss the fields of this structure in the next chapter.)

BeginPaint returns a ”handle to a device context.“ A device context refers to a physical output device (such as a video display) and its device driver. You need the device context handle to display text and graphics in the client area of a window. Using the device context handle returned from BeginPaint, you cannot draw outside the client area, even if you try. EndPaint releases the device context handle so that it is no longer valid. EndPaint also validates the entire client area.

If a window procedure does not process WM_PAINT messages (which is very rare), they must be passed on to DefWindowProc. DefWindowProc simply calls BeginPaint and EndPaint in succession so that the client area is validated.

After WndProc calls BeginPaint, it calls GetClientRect:

GetClientRect (hwnd, &rect) ;

The first parameter is the handle to the program's window. The second parameter is a pointer to a variable named rect defined as type RECT in WndProc.

RECT is a ”rectangle“ structure defined in WINDOWS.H. It has four int fields named left, top, right, and bottom. GetClientRect sets these four fields to the dimensions of the client area of the window. The left and top fields are always set to 0. The right and bottom fields are set to the width and height of the client area in pixels.

WndProc doesn't do anything with this RECT structure except pass a pointer to it as the fourth parameter of DrawText:

DrawText (hdc, "Hello, Windows!", -1, &rect,

DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;

DrawText (as the name implies) draws text. Because this function draws something, the first parameter is a handle to the device context returned from BeginPaint. The second parameter is the text to draw, and the third parameter is set to -1 to indicate that the text string is terminated with a 0 byte.

The last parameter is a series of bit flags defined in WINDOWS.H. The flags indicate that the text should be displayed as a single line centered horizontally and vertically within the rectangle specified by the fourth parameter. This function call thus causes the string ”Hello, Windows!“ to be displayed centered in the client area.

Whenever the client area becomes invalid (as it does when you change the size of the window), Windows erases the background of the window and WndProc receives a new WM_PAINT message. WndProc obtains the updated window size by calling GetClientRect and again displays the text in the new center of the window.