Client-Area Mouse MSG
=====================
Windows sends the keyboard message only to the window that has 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
WM_LBUTTONDOWN
WM_LBUTTONUP
WM_LBUTTONDBCLK
WM_MBUTTONDOWN
WM_MBUTTONUP
WM_MBUTTONDBCLK
WM_RBUTTONDOWN
WM_RBUTTONUP
WM_RBUTTONDBCLK
--------------------------------------------------------------------------------------------------------------------------------------------------
lParam contains the position of the mouse relative to the upper left corner of the client area of the window
X = LOWWORD(lParam) x-coordinate
Y = HIWORD(lParam) y-coordinate
--------------------------------------------------------------------------------------------------------------------------------------------------
wParam indicates the state of the mouse buttons and the Shift and Ctrl keys. 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
Mouse Double-Clicks
================
If you want your window procedure to receive double-click mouse messages, you must include the identifier CS_DBCLKS when initializing the style field in the window class structure before calling RegisterClass:
wndclass.style = CS_HREDRAW | CS_VERDRAW | CS_DBLCLKS
if you do not include CS_DBCLKS in the window style and the user clicks the left mouse button twice in quick succession, your window procedure receives these messages:
WM_LBUTTONDOWN
WM_LBUTTONUP
WM_LBUTTONDOWN
WM_LBUTTONUP
If you includes CS_DBLCLKS in your window class style, the window procedure receives these messages for a double-click:
WM_LBUTTONDOWN
WM_LBUTTONUP
WM_LBUTTONDBLCLK
WM_LBUTTONUP
The WM_LBUTTONDBLCLK message simply reply replaces the second WM_LBUTTONDOWN message.
Double-click messages are much easier to process if the first click of a double-click performs the same action as a single click. The second click then does something in addition to the first click. For example, look at how the mouse works with the file lists in Windows Explorer. A single click selects the file. Windows Explorer highlights the file with a reverse-video bar. A double-click performs two actions: the first click selects the file, just as a single click does; the second click directs Windows Explorer to open the file.
The Hit-Test Message
=======================
WM_NCHITTEST, which stands for “nonclient hit test.” This message precedes all other client-area and nonclient-area mouse messages. The IParam parameter contains the x and y screen coordinates of the mouse position. The wParam parameter is not used.
Windows applications generally pass this message to DefWindowProc, Windows then uses the WM_NCHITTEST message to generate all other mouse messages based on the position of the mouse. For nonclient-area mouse messages, the value returned from DefWindowProc when processing WM_NCHITTEST becomes the wParam parameter in the mouse message. This value can be any of the wParam values that accompany the nonclient-area mouse messages plus the rollowing:
HTCLIENT Client area
HTNOWHERE Not on any window
HTTRANsPARENT A window covered by another window
HTERROR Causes DefWindowProc to produce a beep
If DefWindowProc returns HTCLIENT after it processes a WM_NCHITTEST message, Windows converts the screen coordinates to client-area coordinates and generates a client-area mouse message.
If you remember how we disabled all system keyboard functions by trapping the WM_SYSKEYDOWN message
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
case WM_SYSCHAR:
return 0 ;
you may wonder if you can do something similar by trapping mouse messages. Sure! If you include the lines
case WM_NCHITTEST:
return (LRESULT) HTNOWHERE ;
in your window procedure, you will effectively disable all client-area and nonclient-area mouse messages to your window. The mouse buttons will simply not work while the mouse is anywhere within your window, including the system menu icon, the sizing buttons, and the close button.
Mouse Cursor
==============
Even if a mouse device is not installed, Windows can still display a mouse cursor, Windows maintains something called a "display count" for this cursor. If a mouse is installed, the display count is initially 0; if not, the display count is initially -1. The mouse cursor is displayed only if the display count is non-negative. You can increment the display count by calling
ShowCursor(TRUE);
and decrement it by calling
ShowCursor(FALSE);
Capturing the Mouse
================
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. The window procedure can receive a LBUTTONDOWN without a corresponding WM_LBUTTONUP message if the mouse button is released while positioned over another window.
A window procedure can "capture the mouse" and continue to receive mouse messages even when the mouse is outside the window's client area.
switch(message)
{
case WM_LBUTTONDOWN:
[other program lines]
SetCapture(hwnd);
return 0;
case WM_LBUTTONUP:
[other program lines]
ReleaseCapture();
return 0;
[other program lines]
}