2.3 Window Procedure

A window procedure responds to input and window-management messages received from Windows. The procedure can be short, processing only a message or two, or it can be complex, processing many types of messages for a variety of application windows. In either case, every window must have a window procedure.

A window procedure has the following form:

LRESULT FAR PASCAL MainWndProc(hWnd, message, wParam, lParam)
HWND hWnd;      /* window handle                   */
UINT message;   /* type of message                 */
WPARAM wParam;  /* additional information          */
LPARAM lParam;  /* additional information          */
{
        .
        .
        .

    switch (message) {
        .
        .
        .

        default: /* passes it on if unprocessed    */
            return (DefWindowProc(hWnd, message, wParam, lParam));
    }
    return NULL;
}

The window procedure uses the PASCAL calling convention. Since Windows calls this procedure directly and always uses this convention, PASCAL is required. The window procedure also uses the FAR keyword in its definition, since Windows uses a 32-bit address whenever it calls a procedure or function. Also, you must name the window procedure in an EXPORTS statement in the application's module-definition file. For more information about module-definition files, see Section 2.5, “Creating a Module-Definition File.”

The window procedure receives messages from Windows. These may be input messages that have been dispatched by the WinMain function, or they may be window-management messages that come directly from Windows. The window procedure must examine each message; it then either carries out some specific action based on the message or passes the message back to Windows for default processing by the DefWindowProc function.

The message parameter defines the message type. You use this parameter in a switch statement to direct processing to the correct case. The lParam and wParam parameters contain additional message-dependent information. The window procedure typically uses these parameters to carry out the requested action. If a window procedure does not process a message, it must pass it to DefWindowProc. Passing the message to DefWindowProc ensures that any special actions that affect the window, the application, or Windows itself can be carried out.

Most window procedures process the WM_DESTROY message. Windows sends this message to the window procedure immediately after destroying the window. The message gives the procedure the opportunity to finish its processing and, if it is the window procedure for the application's main window, to post a WM_QUIT message in the application queue. The following example shows how the main window procedure should process this message:

case WM_DESTROY:
    PostQuitMessage(0);
    break;

The PostQuitMessage function places a WM_QUIT message in the application's queue. When the GetMessage function retrieves this message, it terminates the message loop and the application.

A window procedure receives messages from two sources: Input messages come from the message loop, and window-management messages come from Windows. Input messages correspond to mouse input, keyboard input, and sometimes timer input. Typical input messages are WM_KEYDOWN, WM_MOUSEMOVE, WM_KEYUP, and WM_TIMER, all of which correspond directly to hardware input.

Windows sends window-management messages directly to a window procedure without going through the application queue or message loop. These window messages are typically requests for the window procedure to carry out some action, such as painting the client area of its window or supplying information about the window. The messages may also inform the window procedure of changes that Windows has made to the window. Some typical window-management messages are WM_CREATE, WM_DESTROY, and WM_PAINT.

The window procedure should return a 32-bit message-dependent value. For most messages, the return value is arbitrary; cases in which the return value is significant are described in the Microsoft Windows Programmer's Reference, Volume 1. If the window procedure does not process a message, it should return the DefWindowProc function's return value.