一、鼠标基础
通常我们认为键盘便于输入我操作文字数据,而鼠标便于画图和操作图形对象。
我们可以使用GetSystemMetrics函数来确认鼠标是否存在,该函数具体请查阅MSDN
fMouse=GetSystemMetrics(SM_MOUSEPRESENT);
同样,确定鼠标上按键个数:
cButtons=GetSystemMetircs(SM_CMOUSEBUTTOMS);
Windows支持几种预先定义的鼠标光标,程序可以使用这些光标。最常见的是称为IDC_ARROW的斜箭头(在WINUSER.H中定义)。热点在箭头的顶端。在定义窗口类别结构时指定特定窗口的内定光标,例如:
wndclass.hCursor=LoadCursor(NULL,ID_ARROW);
Windows表头文件中定义与鼠标标识符缩写:LBUTTON、MBUTTON、RBUTTON。分别对应鼠标的左,中,右键。
二、显示区域鼠标消息
从前面我们知道键盘只把消息发给拥有输入焦点的窗口。
鼠标消息与此不同的是:只要鼠标跨越窗口或在某窗口按下了鼠标按键。该窗口消息处理函数就会收到鼠标消息。(不管该窗口是否活动或拥有输入焦点)。windows定义了21种鼠标消息,其中11种与显示无关(我们通常称之为“非显示区域消息”)。程序经常忽略这些消息。
当鼠标移过窗口的显示区域时,窗口消息处理程序收到WM_MOUSEMOVE消息。当在窗口的显示区域中按下或者释放一个鼠标按键时,窗口消息
处理程序会接收到下面这些消息:
对于所有这些消息来说,其lParam值均含有鼠标的位置:低字组为x坐标,高字组为y坐标,这两个坐标是相对于窗口显示区域左上角的位置。可用LOWORD和HIWORD宏来提取这些值:
x=LOWORD(lParam);
y=HIWORD(lParam);
wParam的值指示鼠标按键以及Shift和Ctrl键的状态。您可以使用表头文件WINUSER.H中定义的位屏蔽来测试wParam。 MK前缀代表「鼠标按键」。
MK_LBUTTON | 按下左键 |
MK_MBUTTON | 按下中键 |
MK_RBUTTON | 按下右键 |
MK_SHIFT | 按下Shift |
MK_CONTROL | 按下Ctrl |
从上我们可以知道:如果收到了一个WM_RBUTTONDOWN消息同时值wparam&MK_SHIFT非0,就知道是按下鼠标右键的同时也按下了shift键。
这里要注意的是:
1、关于WM_MOUSEMOVE消息:当把鼠标移过窗口的显示区域时, Windows并不为鼠标的每个可能的图素位置都产生一个WM_MOUSEMOVE消息。您的程序接收到WM_MOUSEMOVE消息的次数,依赖于鼠标硬件,以及您的窗口消息处理程序在处理鼠标移动消息时的速度。换句话说Windows不能用未处理的WM_MOUSEMOVE消息来填入消息队列。
2、如果您在非活动窗口的显示区域中按下鼠标左键,那么该非活动窗口变为活动窗口,然后把WM_LBUTTONDOWN消息送到该窗口消息处理程序。当窗口消息处理程序得到WM_LBUTTONDOWN消息时,您的程序就可以安全地假定该窗口是活动化的了。
不过可能在在未接收到WM_LBUTTONDOWN消息的情况下先接收到WM_LBUTTONUP的消息。如在一个窗口中按下鼠标按键,然后移动到使用者窗口释放它。类似的情况,当鼠标按键在另一个窗口中被释放时,窗口消息处理程序只能接收到WM_LBUTTONDOWN消息,而没有相应的WM_LBUTTONUP消息。
上面两规则的例外情况:
1、窗口消息处理程序可以「拦截鼠标」并且连续地接收鼠标消息,即使此时鼠标在该窗口显示区域之外。
2、如果正在显示一个系统模态消息框或者系统模态对话框,那么其它程序就不能接收鼠标消息。当系统模态消息框或者对话框活动时,禁止切换到其它窗口或者程序。
三、非显示区域鼠标消息
非显示区域几乎和显示区域消息想对应。消息中含有字母「 NC」以表示是非显示区域消息。窗口非显示区域包括标题列、菜单和窗口滚动条。比如鼠标在非客户区移动,那么窗口消息处理程序会收到WM_NCMOUSEMOVE消息。产生的消息如下图。
对非显示区域鼠标消息, wParam和lParam参数与显示区域鼠标消息的wParam和lParam参数不同。 wParam参数指明移动或者按鼠标按键的非显示区域。它设定为WINUSER.H中定义的以HT开头的标识符之一(HT表示「命中测试」)。lParam参数低高位为x,y坐标,但是,它们是屏幕坐标对屏幕坐标,显示器左上角的x和y的值为0。当往右移时x的值增加,往下移时y的值增加。
四、命中测试消息
前面已经介绍了21 个鼠标消息中的20个,最后一个消息是WM_NCHITTEST,它代表「非显示区域命中测试」。此消息优先于所有其它的显示区域和非显示区域鼠标消息。 lParam参数含有鼠标位置的x和y屏幕坐标, wParam参数没有用。
Windows应用程序通常把这个消息传送给DefWindowProc,然后Windows用WM_NCHITTEST消息产生与鼠标位置相关的所有其它鼠标消息。对于非显示区域鼠标消息,在处理WM_NCHITTEST时,从DefWindowProc传回的值将成为鼠标消息中的wParam参数,这个值可以是任意非显示区域鼠标消息的wParam值再加上以下内容:
禁用窗口中所有显示区域和非显示区域的鼠标消息。
case WM_NCHITTEST
return (LRESULT)HTNOWHERE
五、拦截鼠标
六、鼠标滑轮