Don't Call Me, I'll Call You

As I mentioned earlier, programmers are familiar with the idea of calling on the operating system to do something. For instance, C programmers use the open or fopen function to open a file. The library functions provided with the compiler have code that eventually calls the operating system to open the file. No problem.

But Windows is different. Although Windows has more than 550 functions that your program can call, Windows also makes calls to your program, specifically to the window procedure we have called WndProc. The window procedure is associated with a window class that the program registers by calling RegisterClass. A window that is created based on this class uses this window procedure for processing all messages to the window. Windows sends a message to the window by calling the window procedure.

Windows calls WndProc when a window is first being created. Windows calls WndProc when the window is later destroyed. Windows calls WndProc when the window has been resized or moved or made into an icon. Windows calls WndProc when an item has been selected from a menu. Windows calls WndProc when a scroll bar is being moved or clicked with the mouse. Windows calls WndProc to tell it when it must repaint its client area.

All these calls are in the form of messages. In most Windows programs, the bulk of the program is dedicated to handling these messages. The 130 or so different messages that Windows can send to a window procedure are all identified with names that begin with the letters WM and defined in WINDOWS.H.

Actually, the idea of a routine within a program that is called from outside the program is not unheard of in normal programming. The signal function in C can trap a Ctrl-Break. You may have experience with intercepting hardware interrupts in assembly language or using one of the ON constructions in Microsoft BASIC. The Microsoft Mouse driver has a method that non-Windows programs can use to be notified of mouse activity.

In Windows, this concept is extended to cover everything. Everything that happens to a window is relayed to the window procedure in the form of a message. The window procedure then responds to this message in some way or passes the message to DefWindowProc for default processing.

The wParam and lParam parameters to the window procedure are not used in HELLOWIN except as parameters to DefWindowProc. These parameters give the window additional information about the message. The meaning of the parameters is message-dependent.

Let's look at an example. Whenever the client area of a window changes in size, Windows calls that window's window procedure. The hwnd parameter to the window procedure is the handle of the window changing in size. The message parameter is WM_SIZE. The wParam parameter for a WM_SIZE message is the value SIZENORMAL, SIZEICONIC, SIZEFULLSCREEN, SIZEZOOMSHOW, or SIZEZOOMHIDE (defined in WINDOWS.H as the numbers 0 through 4). The wParam parameter indicates whether the window is being minimized, maximized, or hidden (as a result of another window being maximized). The lParam parameter contains the new size of the window. The new width (a 16-bit value) and the new height (a 16-bit value) have been stuck together in the 32-byte lParam. WINDOWS.H includes macros to help you extract these two values from lParam. We'll do this in the next chapter.

Sometimes messages generate other messages as a result of DefWindowProc processing. For example, suppose you run HELLOWIN and select Close from the system menu using either the keyboard or the mouse. DefWindowProc processes this keyboard and mouse input. When it detects that you have selected the Close option, it sends a WM_SYSCOMMAND message to the window procedure. WndProc passes this message to DefWindowProc. DefWindowProc responds by sending a WM_CLOSE message to the window procedure. WndProc again passes this message to DefWindowProc. DefWindowProc responds to the WM_CLOSE message by calling DestroyWindow. DestroyWindow causes Windows to send a WM_DESTROY message to the window procedure. WndProc finally responds to this message by calling PostQuitMessage to put a WM_QUIT message in the message queue. This message causes the message loop in WinMain to terminate and the program to end.