Responding to Mouse Clicks
If the user clicks a mouse button while the cursor is over the client area of a window, the window receives one of the following messages.
Message | Meaning |
---|---|
WM_LBUTTONDOWN | Left button down |
WM_LBUTTONUP | Left button up |
WM_MBUTTONDOWN | Middle button down |
WM_MBUTTONUP | Middle button up |
WM_RBUTTONDOWN | Right button down |
WM_RBUTTONUP | Right button up |
WM_XBUTTONDOWN | XBUTTON1 or XBUTTON2 down |
WM_XBUTTONUP | XBUTTON1 or XBUTTON2 up |
Recall that the client area is the portion of the window that excludes the frame. For more information about client areas, see What Is a Window?
Mouse Coordinates
In all of these messages, the lParam parameter contains the x- and y-coordinates of the mouse pointer. The lowest 16 bits of lParam contain the x-coordinate, and the next 16 bits contain the y-coordinate. Use the GET_X_LPARAM and GET_Y_LPARAM macros to unpack the coordinates from lParam.
int xPos = GET_X_LPARAM(lParam);
int yPos = GET_Y_LPARAM(lParam);
These macros are defined in the header file WindowsX.h.
On 64-bit Windows, lParam is 64-bit value. The upper 32 bits of lParam are not used. Where the Windows documentation mentions the "low-order word" and "high-order word" of lParam, the 64-bit case means the low- and high-order words of the lower 32 bits. The macros extract the right values, so if you use them, you will be safe.
Mouse coordinates are given in pixels, not device-independent pixels (DIPs), and are measured relative to the client area of the window. Coordinates are signed values. Positions above and to the left of the client area have negative coordinates, which is important if you track the mouse position outside the window. We will see how to do that in a later topic, Capturing Mouse Movement Outside the Window.
Additional Flags
The wParam parameter contains a bitwise OR of flags, indicating the state of the other mouse buttons plus the SHIFT and CTRL keys.
Flag | Meaning |
---|---|
MK_CONTROL | The CTRL key is down. |
MK_LBUTTON | The left mouse button is down. |
MK_MBUTTON | The middle mouse button is down. |
MK_RBUTTON | The right mouse button is down. |
MK_SHIFT | The SHIFT key is down. |
MK_XBUTTON1 | The XBUTTON1 button is down. |
MK_XBUTTON2 | The XBUTTON2 button is down. |
The absence of a flag means the corresponding button or key was not pressed. For example, to test whether the CTRL key is down:
if (wParam & MK_CONTROL) { ...
If you need to find the state of other keys besides CTRL and SHIFT, use the GetKeyState function, which is described in Keyboard Input.
The WM_XBUTTONDOWN and WM_XBUTTONUP window messages apply to both XBUTTON1 and XBUTTON2. The wParam parameter indicates which button was clicked.
UINT button = GET_XBUTTON_WPARAM(wParam);
if (button == XBUTTON1)
{
// XBUTTON1 was clicked.
}
else if (button == XBUTTON2)
{
// XBUTTON2 was clicked.
}
Double Clicks
A window does not receive double-click notifications by default. To receive double clicks, set the CS_DBLCLKS flag in the WNDCLASS structure when you register the window class.
WNDCLASS wc = { };
wc.style = CS_DBLCLKS;
/* Set other structure members. */
RegisterClass(&wc);
If you set the CS_DBLCLKS flag as shown, the window will receive double-click notifications. A double click is indicated by a window message with "DBLCLK" in the name. For example, a double click on the left mouse button produces the following sequence of messages:
In effect, the second WM_LBUTTONDOWN message that would normally be generated becomes a WM_LBUTTONDBLCLK message. Equivalent messages are defined for right, middle, and XBUTTON buttons.
Until you get the double-click message, there is no way to tell that the first mouse click is the start of a double click. Therefore, a double-click action should continue an action that begins with the first mouse click. For example, in the Windows Shell, a single click selects a folder, while a double click opens the folder.
Non-client Mouse Messages
A separate set of messages are defined for mouse events that occur within the non-client area of the window. These messages have the letters "NC" in the name. For example, WM_NCLBUTTONDOWN is the non-client equivalent of WM_LBUTTONDOWN. A typical application will not intercept these messages, because the DefWindowProc function handles these messages correctly. However, they can be useful for certain advanced functions. For example, you could use these messages to implement custom behavior in the title bar. If you do handle these messages, you should generally pass them to DefWindowProc afterward. Otherwise, your application will break standard functionality such as dragging or minimizing the window.
Next