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 function 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 control every aspect of the way their windows operate.
You must register a window class before you can create a window that belongs to that class. You register a window class by filling a WNDCLASS structure with information about the class, and passing it as a parameter to the RegisterClass function.
The WNDCLASS provides information to Windows about the name, attributes, resources, and window function for a window class. The WNDCLASS data structure contains the following fields:
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
Specifies the application instance that is registering the class.
lpfnWndProc
Points to the window function used to carry out work on the window.
style
Specifies the class styles, such as automatic redrawing of the window when moved or sized.
hbrBackground
Specifies the brush used to paint the window background.
hCursor
Specifies the cursor used in the window.
hIcon
Specifies 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.
clWndExtra
Specifies the number of extra bytes to allocate for all the window structures created with this class.
For more information about these fields, see the Windows Programming Reference.
Some fields, such as lpszClassName, hInstance, and lpfnWndProc, must be assigned values. Other fields can be set to NULL. When these fields 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(hInstance)
HANDLE hInstance; /* current instance */
{
1 WNDCLASS wc;
/* Fill in window class structure with parameters that describe the */
/* main window. */
2 wc.style = NULL; /* Class style(s). */
3 wc.lpfnWndProc = MainWndProc; /* Function to retrieve messages for */
/* windows of this class. */
4 wc.cbClsExtra = 0; /* No per-class extra data. */
wc.cbWndExtra = 0; /* No per-window extra data. */
5 wc.hInstance = hInstance; /* Application that owns the class. */
6 wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
7 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
8 wc.hbrBackground = GetStockObject(WHITE_BRUSH);
9 wc.lpszMenuName = “GenericMenu”; /* Name of menu in .RC file. */
<169> wc.lpszClassName = “GenericWClass”; /* Name used with CreateWindow. */
/* Register the window class and return success/failure code. */
return (RegisterClass(&wc));
}
In this example of a window class structure:
1 | The example first declares that this is a WNDCLASS structure named wc. | |
2 | The style field is set to NULL. | |
3 | The lpfnWndProc field contains a pointer to the window function named MainWndProc. This means that the application's MainWndProc function will then receive any messages that Windows sends to that window, and will be the function that carries out tasks for that window. | |
To assign the address of the MainWndProc function to the lpfnWndProc field, you must declare the function somewhere before the assignment statement. Windows applications should use function prototypes for function declaration in order to take advantage of the compiler's automatic type-checking and casting. The following is the correct prototype for a window function with the name MainWndProc: | ||
long FAR PASCAL MainWndProc (HWND, unsigned, WORD, LONG); | ||
Note that the MainWndProc function must be exported in the module-definition file. | ||
4 | The cbClsExtra and cbWndExtra fields 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 fields to allocate additional storage space which you can then use to store information on a per-window basis.) | |
5 | The hInstance field is set to hInstance, the instance handle that Windows passed to the WinMain function when the application was started. | |
6 | The hIcon field receives a handle to a built-in icon. The LoadIcon function can return a handle to either a built-in 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. For an explanation of how to create and use your own icons, see Chapter 17.) | |
7 | The hCursor field receives a handle to the standard arrow-shaped cursor (pointer). The LoadCursor function can return a handle to either a built-in or an application-defined cursor. In this case, the NULL and IDC_ARROW arguments specify the built-in arrow cursor. (Some applications use their own cursors instead of built-in cursors. For an explanation of how to create and use your own cursors, see Chapter 18.) | |
8 | The hbrBackground field determines the color of the brush that Windows will use to paint the window's background. In this case, the application uses the GetStockObject function to get the handle of the standard white background brush. | |
, | ||
9 | The lpszMenuName field specifies the name of the menu for this window class, GenericMenu. This menu will then appear for all windows in this class. If the window class has no menu, this field is set to NULL. | |
<169> | The lpszClassName field specifies GenericWClass as the class name for this window class. |
After you assign values to the WNDCLASS structure fields, you register the class by using the RegisterClass function. If registration is successful, the function returns TRUE; otherwise, it returns FALSE. 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 the C Compiler. The Windows include 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.