Registering the Window Class

A window is always created based on a window class. The window class identifies the window procedure that processes messages to the window. This is important, so I'll repeat it: A window is always created based on a window class. The window class identifies the window procedure that processes messages to the window.

More than one window can be created based on a single window class. For example, all button windows in Windows are created based on the same window class. The window class defines the window procedure and some other characteristics of the windows that are created based on that class. When you create a window you define additional characteristics of the window that are unique to that window.

Before you create a window for your program, you must register a window class by calling RegisterClass. The RegisterClass function requires a single parameter: a pointer to a structure of type WNDCLASS. The WNDCLASS structure is defined in WINDOWS.H like this:

typedef struct tagWNDCLASS

{

WORD style ;

LONG (FAR PASCAL *lpfnWndProc) () ;

int cbClsExtra ;

int cbWndExtra ;

HANDLE hInstance ;

HICON hIcon ;

HCURSOR hCursor ;

HBRUSH hbrBackground ;

LPSTR lpszMenuName ;

LPSTR lpszClassName ;

}

WNDCLASS ;

In WinMain, you must define a structure of type WNDCLASS, generally like this:

WNDCLASS wndclass ;

You then define the 10 fields of the structure and call RegisterClass:

RegisterClass (&wndclass) ;

Only the first instance of a program needs to register the window class. The window class then becomes available to all subsequent instances of the program. For this reason, HELLOWIN initializes the fields of the WNDCLASS structure and calls RegisterClass only if hPrevInstance equals NULL.

The WNDCLASS structure has 10 fields. The two most important fields are the last and the second. The last field is the name of the window class (which is generally the same as the name of the program). The second field (lpfnWndProc) is the address of the window procedure used for all windows created based on this class (which is the function WndProc in HELLOWIN.C). All the other fields describe characteristics of all windows based on this window class.

The statement:

wndclass.style = CS_HREDRAW | CS_VREDRAW ;

combines two ”class style“ identifiers with a C bitwise OR operator. In WINDOWS.H, the various identifiers beginning with the CS prefix are defined as 16-bit constants with one bit set. For example, CS_VREDRAW is defined as 0x0001, and CS_HREDRAW is defined as 0x0002. Identifiers defined in this way are sometimes called ”bit flags.“ You combine the bit-flag identifiers with the C OR operator.

These two class-style identifiers indicate that all windows created based on this class are to be completely repainted whenever the horizontal window size (CS_HREDRAW) or the vertical window size (CS_VREDRAW) changes. If you resize HELLOWIN's window, you'll see that the text string is redrawn to be in the new center of the window. These two identifiers ensure that this happens.

The second field of the WNDCLASS structure is initialized by the statement:

wndclass.lpfnWndProc = WndProc ;

This sets the window procedure for this window class to WndProc, which is the second function in HELLOWIN.C. This window procedure will process all messages to all windows created based on this window class. The lpfn prefix in the field name is Hungarian notation for ”long pointer to a function.“

The next two statements:

wndclass.cbClsExtra = 0 ;

wndclass.cbWndExtra = 0 ;

reserve some extra space in the class structure and the window structure that Windows maintains internally. A program can use this extra space for its own purpose. HELLOWIN does not use this feature, so zero is specified. The cb prefix in the field names stands for a ”count of bytes.“

The next field is simply the instance handle of the program (which is one of the parameters to WinMain):

wndclass.hInstance = hInstance ;

The statement:

wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;

sets an icon for all windows created based on this window class. The icon is a small bitmap picture that appears when the program is minimized. Later in this book you'll learn how to create customized icons for your Windows programs. Right now, we'll take an easy approach and use a predefined icon.

To obtain a handle to a predefined icon, you call LoadIcon with a first parameter set to NULL. (When loading your own customized icon, this parameter would be set to the instance handle of the program.) The second parameter is an identifier beginning with the IDI (”ID for an icon“) defined in WINDOWS.H. The IDI_APPLICATION icon is simply a white square with a black outline. The LoadIcon function returns a handle to this icon. We don't really care about the value of this handle. It's simply used to set the value of the hIcon field. The hIcon field is defined in the WNDCLASS structure to be of type HICON, which stands for ”handle to an icon.“

The statement:

wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;

is very similar to the previous statement. The LoadCursor function loads a predefined mouse cursor known as IDC_ARROW and returns a handle to the cursor. This handle is assigned to the hCursor field of the WNDCLASS structure. When the mouse cursor appears over the client area of a window that is created based on this class, the cursor becomes a small arrow.

The next field specifies the background color of the client area of windows created based on this class. The hbr prefix of the hbrBackground field name stands for ”handle to a brush.“ A brush is a graphics term that refers to a colored pattern of pixels used to fill an area. Windows has several standard, or ”stock,“ brushes. The GetObject call shown here returns a handle to a white brush:

wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;

This means the background of the client area of the window will be solid white, which is a common choice.

The next field specifies the window class menu. HELLOWIN has no application menu, so the field is set to NULL:

wndclass.lpszMenuName = NULL ;

Finally the class must be given a name. This is the same as the name of the program, which is the ”HelloWin“ string stored in the szAppName variable:

wndclass.lpszClassName = szAppName ;

When all 10 fields of the structure have been initialized, HELLOWIN registers the window class by calling RegisterClass. The only parameter to the function is a pointer to the WNDCLASS structure:

RegisterClass (&wndclass) ;