2008 November 12th Wednesday (十一月 十二日 水曜日)

   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. These are called "nonclient-area messages," and Windows applications
usually ignore them.

  Your window procedure receives MBUTTON messages only for a three-button mouse and RBUTTON messages only for a two-button
mouse. The window procedure receives DBLCLK (double-click) messages only if the window class has been defined to receive them.

  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 these values
using the LOWORD and HIWORD macros:

x = LOWORD (lParam) ;
y = HIWORD (lParam) ;

  The value of wParam indicates the state of the mouse buttons and the Shift and Ctrl keys. You can test wParam using these
bit masks defined in the WINUSER.H header file. 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

  For example, if you receive a WM_LBUTTONDOWN message, and if the value

wparam & MK_SHIFT

is TRUE (nonzero), you know that the Shift key was down when the left button was pressed.

  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. In other words,
Windows does not fill up a message queue with unprocessed WM_MOUSEMOVE messages.

  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 while the box is active.
  An example of a system modal message box is the one that appears when you shut down your Windows session.

Mouse Double-Clicks

  A mouse double-click is two clicks in quick succession. To qualify as a double-click, the two clicks must occur in
close physical proximity of one another (by default, about an area as wide as an average system font character and half
as high) and within a specific interval of time called the "double-click speed." You can change that time interval in
the Control Panel.

  If you want your window procedure to receive double-click mouse messages, you must include the identifier CS_DBLCLKS
when initializing the style field in the window class structure before calling RegisterClass:

wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS ;

  If you do not include CS_DBLCLKS 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

  The window procedure might also receive other messages between these button messages. If you want to implement your own
double-click logic, you can use the Windows function GetMessageTime to obtain the relative times of the WM_LBUTTONDOWN messages.

  If you include 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 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 (the WM_LBUTTONDBLCLK message) 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. That's fairly easy logic. Mouse-handling logic could get more complex if the first click of a double-click did
not perform the same action as a single click.

The Hit-Test Message

  If you've been keeping count, you know that so far we've covered 20 of the 21 mouse messages. The last message is WM_NCHITTEST, which
stands for "nonclient hit test." This message precedes all other client-area and nonclient-area mouse messages. The lParam 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 following:

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, 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.

Messages Beget Messages

  Windows uses the WM_NCHITTEST message to generate all other mouse messages. The idea of messages giving birth to other messages is common
in Windows. Let's take an example. As you may know, if you double-click the system menu icon of a Windows program, the window will be terminated.
The double-click generates a series of WM_NCHITTEST messages. Because the mouse is positioned over the system menu icon, DefWindowProc returns
a value of HTSYSMENU and Windows puts a WM_NCLBUTTONDBLCLK message in the message queue with wParam equal to HTSYSMENU.

  The window procedure usually passes that mouse message to DefWindowProc. When DefWindowProc receives the WM_NCLBUTTONDBLCLK message with wParam
equal to HTSYSMENU, it puts a WM_SYSCOMMAND message with wParam equal to SC_CLOSE in the message queue. (This WM_SYSCOMMAND message is also generated
when a user selects Close from the system menu.) Again the window procedure usually passes that message to DefWindowProc. DefWindowProc processes
the message by sending a WM_CLOSE message to the window procedure.

  If the program wants to require confirmation from a user before terminating, the window procedure can trap WM_CLOSE. Otherwise, DefWindowProc
processes WM_CLOSE by calling the DestroyWindow function. Among other chores, DestroyWindow sends a WM_DESTROY message to the window procedure. Normally,
a window procedure processes WM_DESTROY with the code

case WM_DESTROY:
     PostQuitMessage (0) ;
     return 0 ;

  The PostQuitMessage causes Windows to place a WM_QUIT message in the message queue. This message never reaches the window procedure because it
causes GetMessage to return 0, which terminates the message loop and the program.

  Capturing the mouse is easier than baiting a mousetrap. You need only call

SetCapture (hwnd) ;

  After this function call Windows sends all mouse messages to the window procedure for the window whose handle is hwnd. The mouse messages
always come through as client-area messages, even when the mouse is in a nonclient area of the window. The lParam parameter still indicates
the position of the mouse in client-area coordinates. These x and y coordinates, however, can be negative if the mouse is to the left of or
above the client area. When you want to release the mouse, call

ReleaseCapture () ;

which will returns things to normal.

  In the 32-bit versions of Windows, mouse capturing is a bit more restrictive than it was in earlier versions of Windows. Specifically, if
the mouse has been captured, and if a mouse button is not currently down, and if the mouse cursor passes over another window, the window
underneath the cursor will receive the mouse messages rather than the window that captured the mouse. This is necessary to prevent one program
from messing up the whole system by capturing the mouse and not releasing it.

  To avoid problems, your program should capture the mouse only when the button is depressed in your client area. You should release the
capture when the button is released.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值