2.2.4 Registering a Window Class

Before you can create any window, you must have a window class. A window class is a template that defines the attributes of a window, such as the shape of the window's cursor and the name of the window's menu. The window class also specifies the window procedure that processes messages for all windows in the class. Although Windows provides some predefined window classes, most applications define their own window classes in order to completely control how their windows operate.

You must register a window class before you can create a window that belongs to that class. You do this by filling a WNDCLASS structure with information about the class and passing it as a parameter to the RegisterClass function.

2.2.4.1 Filling a WNDCLASS Structure

The WNDCLASS structure provides information to Windows about the name, attributes, resources, and window procedure for a window class. The WNDCLASS structure contains the following members:

Member Description

lpszClassName Points to the name of the window class. A window class name must be unique; that is, different applications must use different class names.
hInstance Identifies the application instance that is registering the class.
lpfnWndProc Points to the window procedure used to carry out work on the window.
style Specifies the class styles, such as automatic redrawing of the window whenever it is moved or sized.
hbrBackground Identifies the brush used to paint the window background.
hCursor Identifies the cursor used in the window.
hIcon Identifies the icon used to represent a minimized window.
lpszMenuName Points to the resource name of a menu.
cbClsExtra Specifies the number of extra bytes to allocate for this class structure. The extra bytes are initialized to zero.
clWndExtra Specifies the number of extra bytes to allocate for all the window structures created with this class. The extra bytes are initialized to zero.

For more information about these members, see the Microsoft Windows Programmer's Reference, Volume 3.

Some members, such as lpszClassName, hInstance, and lpfnWndProc, must be assigned values. Other members can be set to NULL. When these members are set to NULL, Windows uses a default attribute for windows created using the class. The following example shows how to fill a window structure:

BOOL InitApplication(hinstCurrent)
HINSTANCE hinstCurrent;  /* current instance                       */
{
    WNDCLASS  wc;

    /*
     *  Fill in window-class structure with parameters that
     *  describe the main window.
     */

    wc.style = NULL;                /* class style(s)              */
    wc.lpfnWndProc = MainWndProc;   /* window procedure            */
                                    /* for windows of this class   */

    wc.cbClsExtra = 0;              /* no per-class extra data     */
    wc.cbWndExtra = 0;              /* no per-window extra data    */

    wc.hInstance = hinstCurrent;    /* application that owns class */
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = GetStockObject(WHITE_BRUSH);
    wc.lpszMenuName =  "GenericMenu";   /* menu name in .RC file   */
    wc.lpszClassName = "GenericWClass"; /* name in CreateWindow    */

    /* Register the window class and return success/failure code.  */

    return (RegisterClass(&wc));
}

This example first declares a WNDCLASS structure named wc.

The style member is set to NULL.

The lpfnWndProc member contains a pointer to the window procedure named MainWndProc. This means that the application's MainWndProc procedure will receive any messages that Windows sends to that window and will be the procedure that carries out tasks for that window. To assign the address of MainWndProc to the lpfnWndProc member, you must declare the procedure somewhere before the assignment statement. Windows applications should use prototypes for declaring procedures in order to take advantage of the automatic type-checking and casting provided by CL. The following is the correct prototype for a window procedure with the name MainWndProc:

LRESULT FAR PASCAL MainWndProc(HWND, UINT, WPARAM, LPARAM);

Note that the MainWndProc procedure must be exported in the module-definition file.

The cbClsExtra and cbWndExtra members are set to zero, so there is no additional storage space associated with either the window class or each individual window. (You can set these members to allocate additional storage space, which you can then use to store information on a per-window basis. For information about using this extra space, see Chapter 16, “More Memory Management.”

The hInstance member is set to hinstCurrent, the instance handle that Windows passed to the WinMain function when the application was started.

The hIcon member receives a handle to a built-in icon. The LoadIcon function can return a handle to either a built-in icon or an application-defined icon. In this case, the NULL and IDI_APPLICATION arguments specify the built-in application icon. (Most applications use their own icons instead of the built-in application icon. Chapter 5, “Icons,” explains how to create and use your own icons.)

The hCursor member receives a handle to the standard arrow-shaped cursor. The LoadCursor function can return a handle to either a built-in cursor or an application-defined cursor. In this case, the NULL and IDC_ARROW arguments specify a built-in arrow cursor. (Some applications use their own cursors instead of built-in cursors. Chapter 6, “Cursors,” explains how to create and use your own cursors.)

The hbrBackground member determines the color of the brush that Windows is to use to paint the window's background. In this case, the application uses the GetStockObject function to retrieve the handle of the standard white background brush.

The lpszMenuName member specifies the name of the menu for this window class, GenericMenu. This menu then appears for all windows in this class. If the window class has no menu, this member is set to NULL.

The lpszClassName member specifies GenericWClass as the class name for this window class.

2.2.4.2 Using the RegisterClass Function

After you assign values to the WNDCLASS structure members, you register the class by using the RegisterClass function. If registration is successful, the function returns a nonzero value; otherwise, it returns zero. Make sure you check the return value, because you cannot create your windows without first registering the window class.

Although the RegisterClass function requires a 32-bit pointer to a WNDCLASS structure, in the previous example, the address operator (&) generates only a 16-bit address. This is an example of an implicit cast carried out by CL. The Windows header file contains prototypes for all Windows functions. These prototypes specify the correct types for each function parameter, and the compiler casts to these types automatically.