Coloring the Background

When COLORS1 defines its window class, it gives the background of its client area a solid black brush:

wndclass.hbrBackground = CreateSolidBrush (0L) ;

When you change the settings of COLORS1's scroll bars, the program must create a new brush and put the new brush handle in the window class structure. Just as we were able to get and set the scroll bar window procedure using GetWindowLong and SetWindowLong, we can get and set the handle to this brush using GetClassWord and SetClassWord.

First you must delete the existing brush:

DeleteObject (GetClassWord (hwnd, GCW_HBRBACKGROUND)) ;

Then you can create the new brush and insert the handle in the window class structure:

SetClassWord (hwnd, GCW_HBRBACKGROUND,

CreateSolidBrush (RGB (color[0], color[1], color[2]))) ;

The next time Windows recolors the background of the window, Windows will use this new brush. To force Windows to erase the background, we invalidate the entire client area:

InvalidateRect (hwnd, NULL, TRUE) ;

The TRUE (nonzero) value as the third parameter indicates that we want the background erased before repainting.

InvalidateRect causes Windows to put a WM_PAINT message in the message queue of the window procedure. Because WM_PAINT messages are low priority, this message will not be processed immediately if you are still moving the scroll bar with the mouse or the cursor keys. Alternatively, if you want the window to be updated immediately after the color is changed, you can add the statement:

UpdateWindow (hwnd) ;

after the InvalidateRect call. But this slows down keyboard and mouse processing.

COLORS1's WndProc function doesn't process the WM_PAINT message but passes it to DefWindowProc. Window's default processing of WM_PAINT messages simply involves calling BeginPaint and EndPaint to validate the window. Because we specified in the InvalidateRect call that the background should be erased, the BeginPaint call causes Windows to generate a WM_ERASEBKGND (erase background) message. WndProc ignores this message also. Windows processes it by erasing the background of the client area using the brush specified in the window class.

Normally, Windows would erase the entire client area using the window class brush. Doing so would erase the 10 child windows, however, and Windows would then have to send WM_PAINT messages to all the child windows so they could repaint themselves_ very annoying. We avoid the problem by using the WS_CLIPCHILDREN style value when first creating the parent window using CreateWindow; this style prevents the parent window from painting over its children. Take the WS_CLIPCHILDREN style out of CreateWindow, and you'll see a big difference in how COLORS1 works.

Like all GDI objects, the brushes created by a program using CreateSolidBrush are not automatically deleted by Windows when the program terminates. We've been good about deleting each brush before creating a new one, but when the program is about to terminate, one last brush in the window class still should be discarded. Thus, during processing of the WM_DESTROY message, DeleteObject is called once more:

DeleteObject (GetClassWord (hwnd, GCW_HBRBACKGROUND)) ;