In the previous chapter you saw how Windows sends keyboard messages only to the window with the input focus. Mouse messages are different: A window procedure receives mouse messages whenever the mouse passes over the window or is clicked within the window, even if the window is not active or does not have the input focus.
Windows defines 21 messages for the mouse. However, 11 of these messages do not relate to the client area (hereinafter, ”nonclient-area“ messages), and Windows programs usually ignore them. Of the 10 ”client-area“ mouse messages, 6 pertain to the right and middle buttons. Windows programs usually ignore these messages also.
When the mouse is moved over the client area of a window, the window procedure receives the message WM_MOUSEMOVE. When a mouse button is pressed or released within the client area of a window, the window procedure receives these messages:
Button | Pressed | Released | Pressed (2d Click) |
Left | WM_LBUTTONDOWN | WM_LBUTTONUP | WM_LBUTTONDBLCLK |
Middle | WM_MBUTTONDOWN | WM_MBUTTONUP | WM_MBUTTONDBLCLK |
Right | WM_RBUTTONDOWN | WM_RBUTTONUP | WM_RBUTTONDBLCLK |
Your window procedure receives ”MBUTTON“ messages only for a three-button mouse and ”RBUTTON“ messages only for a two-button or three-button mouse. The window procedure receives ”DBLCLK“ (double-click) messages only if the window class has been defined to receive them (as described below).
For all these messages, the value of lParam contains the position of the mouse. The low word is the x-coordinate, and the high word is the y-coordinate relative to the upper left corner of the client area of the window. You can extract the x-coordinate and y-coordinate from lParam using the LOWORD and HIWORD macros defined in WINDOWS.H. The value of wParam indicates the state of the mouse buttons and the Shift and Ctrl keys. You can test wParam using the bit masks defined in WINDOWS.H. The MK prefix stands for ”mouse key.“
MK_LBUTTON | Left button is down |
MK_MBUTTON | Middle button is down |
MK_RBUTTON | Right button is down |
MK_SHIFT | Shift key is down |
MK_CONTROL | Ctrl key is down |
As you move the mouse over the client area of a window, Windows does not generate a WM_MOUSEMOVE message for every possible pixel position of the mouse. The number of WM_MOUSEMOVE messages your program receives depends on the mouse hardware and on the speed at which your window procedure can process the mouse movement messages. You'll get a good idea of the rate of WM_MOUSEMOVE messages when you experiment with the CONNECT program described below.
If you click the left mouse button in the client area of an inactive window, Windows changes the active window to the window that is being clicked and then passes the WM_LBUTTONDOWN message to the window procedure. When your window procedure gets a WM_LBUTTONDOWN message, your program can safely assume the window is active. However, your window procedure can receive a WM_LBUTTONUP message without first receiving a WM_LBUTTONDOWN message. This can happen if the mouse button is pressed in one window, moved to your window, and released. Similarly, the window procedure can receive a WM_LBUTTONDOWN without a corresponding WM_LBUTTONUP message if the mouse button is released while positioned over another window.
There are two exceptions to these rules:
A window procedure can ”capture the mouse“ and continue to receive mouse messages even when the mouse is outside the window's client area. You'll learn how to capture the mouse later in this chapter.
If a system-modal message box or a system-modal dialog box is on the display, no other program can receive mouse messages. System-modal message boxes and dialog boxes prohibit switching to another window or
program while the box is active. (An example of a system-modal message box is the one that says ”This will end your Windows session“ when you close the Program Manager.)