关于鼠标输入
鼠标是一个重要的,但可选的输入设备,好的应用程序应该包括鼠标接口,但不应该把鼠标作为唯一的输入设备,而也应该提供完备的键盘支持。
应用程序是以接收发送到或者投递到窗口的消息的方式获取鼠标输入的。
本节包含以下内容:
鼠标光标
当用户移动鼠标时,系统屏幕上的一个图形也跟着移动,这个图形就叫做鼠标光标。鼠标光标包含一个单像素的点称为热点,系统根据该点移动或识别光标位置。当产生鼠标事件时,包含热点的窗口就会收到事件所产生的消息。接收消息的窗体没有必要是激活的窗体,或者获取了键盘焦点。
系统维护着控制鼠标移动速度的变量—也就是,用户移动鼠标时,光标所移动的距离。 可以使用SystemParametersInfo 函数并指定SPI_GETMOUSE或SPI_SETMOUSE标志以获取或设置鼠标速度。更多关于光标的信息,请参见“光标”。
鼠标捕获
当发生鼠标事件时,系统通常会把一个鼠标消息发送到包含鼠标热点的窗体中,应用程序可以通过使用SetCapture函数把鼠标信息转而传递给指定的窗口。在调用ReleaseCapture或者指定另外一个捕获窗体,更一般的情况是用户点击了其他线程创建的窗体前,该窗口就会接收所有的鼠标信息。
鼠标捕获改变时,系统就会给失去捕获的窗口发送 WM_CAPTURECHANGED消息。消息的lParam参数为获得捕获的窗体句柄。
只有前台的窗体才可以捕获鼠标输入,如果后台窗体尝试捕获的话,只有热点在窗体的可见部分时才会引发鼠标事件消息。
如果一个窗体必须接收所有的鼠标事件,即便光标移到了窗口之外,捕获鼠标输入就很有用了。例如,涌涌程序可能会跟踪按下一个鼠标键后的光标位置,跟着光标移动鼠标,直到释放鼠标键。如果应用程序没有捕获鼠标输入的话,用户在窗体外释放鼠标键时,该窗体就不会收到button-up消息了。
线程中可以使用GetCapture函数确定是否有一个它的窗口正在捕获鼠标,如果发现一个窗口正在捕获的话,GetCapture函数就会获取该窗口的句柄。
鼠标单击锁
鼠标单击锁(ClickLock)是Microsoft® Windows® Millennium Edition (Windows Me)及Windows XP中新增的辅助选项,该功能允许用户点击主键后锁定为按下状态,对于应用程序来说该键看起来是按下去的,应用程序可以通过发送任意的鼠标消息或用户单击任意键来释放该键。该特点可以使得用户做复杂的鼠标组合时变得简单。如,突出显示、拖拽或者打开菜单时就会很容易。更多信息,请参阅SystemParametersInfo及如下标志的详细描述:
- SPI_GETMOUSECLICKLOCK
- SPI_SETMOUSECLICKLOCK
- SPI_GETMOUSECLICKLOCKTIME
- SPI_SETMOUSECLICKLOCKTIME
鼠标设置
尽管鼠标是一个重要的输入设备,但并不是每个用户都需要鼠标。应用程序通过调用GetSystemMetrics函数,并传入SM_MOUSEPRESENT,就会确定系统中是否安装了鼠标。
Windows可以支持三键的鼠标,三键鼠标包含左键、中键及右键,消息及鼠标的常量命名中依次用L、M及R标识三个键。单键鼠标的按键被认为是左键。尽管Windows支持多键鼠标,但大多数应用程序还是主要用左键,其他键反而极少使用。
从Windows 98及Microsoft Windows NT® 4.0开始,应用程序也可以支持鼠标滚轮了,鼠标滚轮可以被按下或者滚动。鼠标滚轮被按下时,担当中键(第三键)的作用,并发送一般的中键消息。滚轮旋转时,应用程序就会收到滚轮消息。更多信息请参照“鼠标滚轮”节。
从Windows 2000开始,应用程序可以支持应用程序命令键了,这些键被称为X键,使之能更方便地访问Internet浏览器、电子邮件及媒体服务。当X键按下时,应用程序会收到一个WM_APPCOMMAND消息。更多信息,请参照WM_APPCOMMAND消息的详细说明。
应用程序通过向GetSystemMetrics传递SM_CMOUSEBUTTONS可以确定鼠标的按键个数。要为用户设置左手习惯,可以通过SwapMouseButton函数交换意义上的左右键。通过传递SPI_SETMOUSEBUTTONSWAP给SystemParametersInfo函数也可以调换左右键。注意:鼠标是一个共享资源,调换左右键同样会影响其他的应用程序。
XBUTTONs
从Windows 2000开始, Microsoft可以支持Microsoft IntelliMouse® Explorer,就是一个具有五个键的鼠标。除了通常的左键、中间及右键外,还包括XBUTTON1及XBUTTON2两个键,这两个键在使用Microsoft Internet Explorer时可以提供浏览器的前进、后退功能。
Windows管理器通过WM_XBUTTON*及WM_NCXBUTTON*消息可以支持XBUTTON1、XBUTTON2键,这些消息中WPARAM消息中的高字(HIWORD)包含的一个标志说明按下了那个X键。由于这些鼠标消息也介于WM_MOUSEFIRST与WM_MOUSELAST之间,所以应用程序可以通过GetMessage或者PeekMessage筛选所有的鼠标消息。
Windows 2000/XP: 下面是支持XBUTTON1、XBUTTON2的消息:
- WM_APPCOMMAND
- WM_NCXBUTTONDBLCLK
- WM_NCXBUTTONDOWN
- WM_NCXBUTTONUP
- WM_XBUTTONDBLCLK
- WM_XBUTTONDOWN
- WM_XBUTTONUP
- MOUSEHOOKSTRUCTEX
下列API已更新,并可以支持新的鼠标键了:
- mouse_event
- ShellProc
- MSLLHOOKSTRUCT
- MOUSEINPUT
- WM_PARENTNOTIFY
由于组件程序中的子窗体不能直接执行XBUTTON1与XBUTTON2的命令,所以当X键单击时,DefWindowProc会发送一个WM_APPCOMMAND消息到一个窗口,同时也会发送该消息给它的父窗体。类似于鼠标右键的上下文菜单的方式—DefWindowProc发送一个 WM_CONTEXTMENU 到菜单,同时也会发送给它的父亲。另外,如果DefWindowProc收到一个顶级窗口的WM_APPCOMMAND消息,它会以代码HSHELL_APPCOMMAND调用shell hook。
Windows 2000/XP: 支持键盘的额外浏览功能键、媒体功能键、应用载入键及电源管理键,更多信息,请参照“键盘的浏览及其他功能键”。
鼠标消息
鼠标移动、按下或释放都会产生鼠标消息。系统把鼠标输入事件转换为消息,并投递到相应的线程消息队列。如果消息投递过快,线程处理不过来的话,系统就会遗弃原来的消息,而仅处理最近的鼠标消息了。
鼠标在窗体内移动、按下或释放时,又或者该窗体捕获鼠标时,当事件产生,窗体就会收到相应的鼠标消息。鼠标消息可以分为两类:客户区域消息及非客户区域消息。通常,应用程序仅处理客户区域消息,而忽略非客户区域消息。
本节包含以下内容:
- 客户区域的鼠标消息
- 非客户区域的鼠标消息
- WM_NCHITTEST消息
客户区域的鼠标消息
在窗体的客户区域内发生鼠标事件时,该窗体就会收到客户区域的鼠标消息。这时,如果是移动光标的话,系统就会投递 WM_MOUSEMOVE消息;如果是按下或释放一个鼠标键时就会投递以下消息之一:
| 消息 | 含义 |
|---|---|
| WM_LBUTTONDBLCLK | 左键双击 |
| WM_LBUTTONDOWN | 按下左键 |
| WM_LBUTTONUP | 释放左键 |
| WM_MBUTTONDBLCLK | 中键双击 |
| WM_MBUTTONDOWN | 按下中键 |
| WM_MBUTTONUP | 释放中键 |
| WM_RBUTTONDBLCLK | 右键双击 |
| WM_RBUTTONDOWN | 按下右键 |
| WM_RBUTTONUP | 释放右键 |
| WM_XBUTTONDBLCLK | Windows 2000/Windows XP: X键双击 |
| WM_XBUTTONDOWN | Windows 2000/Windows XP: 按下X键 |
| WM_XBUTTONUP | Windows 2000/Windows XP: 释放X键 |
另外,应用程序可以通过调用TrackMouseEvent函数以获取系统发送的另外两个消息:WM_MOUSEHOVER、WM_MOUSELEAVE。WM_MOUSEHOVER消息是鼠标进入客户区域时产生的,WM_MOUSELEAVE是光标离开客户区域时产生的。
消息参数
客户区域消息的lParam参数描述了鼠标热点的位置,低字部分为x坐标,高字部分为y坐标。坐标系为客户区域内坐标系,客户区域内左上角的坐标为(0,0)。
wParam参数包含了发生事件时其他键的状态以及CTRL、SHIFT键的状态。处理鼠标消息时,你可以通过检查这些值来确定鼠标键的状态或CTRL、SHIFT键的状态,wParam可以为下列值的组合:
| 值 | 含义 |
|---|---|
| MK_CONTROL | 按下CTRL键 |
| MK_LBUTTON | 按下鼠标左键 |
| MK_MBUTTON | 按下鼠标中键 |
| MK_RBUTTON | 按下鼠标右键 |
| MK_SHIFT | 按下SHIFT键 |
| MK_XBUTTON1 | Windows 2000/Windows XP: 按下了第一个X鼠标键 |
| MK_XBUTTON2 | Windows 2000/Windows XP: 按下了第二个X鼠标键 |
双击消息
如果快速连续单击两次的鼠标的话,系统就会产生双击消息。当用户单击一个按键时,系统就会以热点为中心在点周围建立一个矩形区域,同时记录单击的时间,当用户第二次单击同一个键时,系统就会确定热点是否仍在矩形区域内,并且计算自上一次单击的时间,如果热点仍在矩形区域内,并且流逝的时间没有超过双击定义的超时期限时,系统就产生了一个双击消息。
应用程序可以通过GetDoubleClickTime及SetDoubleClickTime函数可以获取或设置双击超时期限。另外,应用程序也可以调用SystemParametersInfo函数时传递SPI_SETDOUBLECLICKTIME标志来设置双击超时期限,传递SPI_SETDOUBLECLKWIDTH与SPI_SETDOUBLECLKWIDTH设置检测双击的矩形框的大小。然而需要注意的是,所有修改将影响其他应用程序。
应用程序定义的窗体默认不接收双击消息,因为系统之前已经作了双击消息处理,仅属于那些具有CS_DBCLKS类风格的窗体实例会产生这些消息。如果需要接收双击消息的话,你的应用程序也必须在注册Window类时设置该风格。更多信息,请参见 Window Classes。
双击消息总会是消息系列中的第三个消息,前两个是第一次单击时的button-down与button-up消息,第二次单击才会产生双击消息及另外的一个button-up消息。例如,双击左键就会产生以下消息序列:
- WM_LBUTTONDOWN
- WM_LBUTTONUP
- WM_LBUTTONDBLCLK
- WM_LBUTTONUP
由于收到双击消息前总是会收到一个button-down消息,所以应用程序通常使用双击消息来扩充执行button-down消息所开始的任务。例如,Microsoft Paint的调色板,用户单击一个调色板的颜色时,画图就会显示调色板将会使用的用户所选择的颜色,当双击是,画图就会显示这个颜色,并打开“编辑颜色”对话框。
非客户区域消息
如果鼠标在窗体除客户区域外的部分引发鼠标事件的话,窗体就会收到一个非客户区域消息。非客户区域由边框、菜单栏、标题栏、滚动条、系统菜单、最小化、最大化组成。
非客户区域消息主要是为了系统自身使用,比如,当热点移到窗口边框上时,系统用非客户区域消息把鼠标光标变为两个箭头的光标。窗体必须传递非客户区域消息给DefWindowProc函数,以便利用内置的鼠标处理接口。
对于客户区域的鼠标消息来说,也有一个非客户区域的鼠标消息对应。名字也很类似,只不过非客户区域消息的常量中包含了“NC”。例如,非客户区域内移动光标将产生WM_NCMOUSEMOVE消息,按下鼠标左键将产生WM_NCLBUTTONDOWN消息。
非客户区域消息的lParam参数是包含热点x坐标及y坐标的结构,同客户区域坐标系不同,该坐标是以屏幕坐标系来表示的。屏幕坐标系的(0,0)点表示屏幕的左上角。
wParam参数包含一个hit-test值,hit-test用来指出非客户区域消息是在哪引发的。下面就会对hit-test作详细介绍。
WM_NCHITTEST消息
只要鼠标事件产生,系统就会发送一个WM_NCHITTEST消息到鼠标热点所在窗口或鼠标捕获的窗口。系统根据该消息确定应该发送一个客户区域消息还是非客户区域消息。要想接收鼠标移动及鼠标键消息,就要求应用程序必须在调用DefWindowProc函数时传递WM_NCHITTEST消息。
WM_NCHITTEST消息的lParam参数包含鼠标热点的屏幕坐标,DefWindowProc函数会检查该坐标,并返回一个hit-test值,其中包含了热点的位置。hit-test值可以为下列值之一:
| 值 | 热点所在位置 |
|---|---|
| HTBORDER | 不能改变大小的窗口的边框 |
| HTBOTTOM | 下边框 |
| HTBOTTOMLEFT | 边框的左下角 |
| HTBOTTOMRIGHT | 边框的右下角 |
| HTCAPTION | 标题栏 |
| HTCLIENT | 客户区域 |
| HTCLOSE | 关闭按钮 |
| HTERROR | 屏幕背景或窗口间的分界线上(与HTNOWHERE相同,但不包括DefWindowProc函数引发beep的错误的位置) |
| HTGROWBOX | 缩放格(同HTSIZE) |
| HTHELP | 帮助按钮 |
| HTHSCROLL | 水平滚动条 |
| HTLEFT | 窗口的左边框 |
| HTMENU | 菜单中 |
| HTMAXBUTTON | 最大化按钮 |
| HTMINBUTTON | 最小化按钮 |
| HTNOWHERE | 屏幕背景或窗口间的分界线上 |
| HTREDUCE | 最小化按钮 |
| HTRIGHT | 窗口的右边框 |
| HTSIZE | 缩放格(同HTGROWBOX). |
| HTSYSMENU | 系统菜单或子窗体的关闭按钮上 |
| HTTOP | 窗口的上边框 |
| HTTOPLEFT | 边框的左上角 |
| HTTOPRIGHT | 边框的右上角 |
| HTTRANSPARENT | 在被同一线程的另一个窗口覆盖的窗口上 |
| HTVSCROLL | 垂直滚动条 |
| HTZOOM | 最大化按钮 |
如果鼠标光标在窗口的客户区域内,DefWindowProc将返回HTCLIENT给窗口处理过程。窗口处理过程把该值返回给系统,然后系统转换热点的屏幕坐标为客户区域坐标,接着再投递相应的客户区域消息。
当热点在窗口的非客户区域内时,DefWindowProc函数就会返回其他的hit-test值之一,当窗口处理过程反馈该值时,系统就会投递非客户区域消息,其中把该hit-test值放在wParam参数内,光标坐标放在lParam参数内。
鼠标声纳(mouse sonar)
Windows Me及Windows XP中增加了鼠标测距的功能,该功能会在用户按下、释放CTRL键时在热点周围显示几个同心圆。本功能可以让用户在杂乱(或者分辨率变高后)的桌面上迅速定位鼠标指针,在一个低劣的显示器上,可以减少对用户视力的损害。更多信息,请参照SystemParametersInfo的如下标志:
SPI_GETMOUSESONAR
SPI_SETMOUSESONAR
隐藏鼠标
Windows Me及Windows XP中包含了隐藏鼠标的功能,这可以使得用户打字时隐藏鼠标。移动鼠标的话就会重新出现,只要是输入文本,鼠标就会保持不显示,例如,输入邮件或其他文档时。详细信息,请参照SystemParametersInfo的如下标志:
SPI_GETMOUSEVANISH
SPI_SETMOUSEVANISH
鼠标滚轮
鼠标滚轮组合了滚轮及键的作用,滚轮上有不连续的均匀分布的槽口,当旋转滚轮时,每遇到一个槽口就会产生一个滚轮消息。滚轮键可以作为一个普通的Windows中键(或者说第三键)使用。按下或释放鼠标滚轮将发送标准的WM_MBUTTNUP及WM_MBUTTONDOWN消息,双击的话发送WM_MBUTTONDBLCLK消息。
Windows 95, Windows NT 3.51: 通过作为IntelliMouse pointing device的单独运行模块产生的MSH_MOUSEWHEEL消息提供鼠标滚轮支持。
Windows 98/Me, Windows NT 4.0 and later: WM_MOUSEWHEEL消息 提供滚轮 支持。
在大多数情况下,应用程序显式的处理WM_MOUSEWHEEL与MSH_MOUSEWHEEL消息,然而这两个消息还是有以下重要区分:
- MSH_MOUSEWHEEL中不包含fwKeys;
- MSH_MOUSEWHEEL包含了zDelta参数。
- 对于MSH_MOUSEWHEEL,DefWindowProc不会执行任何特定的处理。
- WM_MOUSEWHEEL消息首先传递给获取焦点的控件,并通过DefWindowProc函数传递给它的父窗体。MSH_MOUSEWHEEL首先传递到最上层父亲,并且必须被应用程序转寄给获得焦点的控件。
- 应用程序处理WM_MOUSEWHEEL消息时,必须返回0。但处理MSH_MOUSEWHEEL消息时,必须返回TRUE。
下列章节分别概述了的两个消息处理过程:
WM_MOUSEWHEEL消息
Windows 98/Me, Windows NT 4.0 and later: 通过WM_MOUSEWHEEL消息提供旋转滚轮支持。
旋转滚轮将向获得焦点的窗口发送WM_MOUSEWHEEL消息。DefWindowProc函数会把消息传递给父窗体。由于DefWindowProc按照父窗体链依次传递该消息,直到有一个窗体处理,所以不应该再有内部转寄的消息了。
确定滚动的行数
应该使用SystemParametersInfo函数得到每次滚动(滚轮槽口)一个文档滚动的行数。应用程序通过下述调用就可以得到滚动的行数:
SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, pulScrollLines, 0)
"pulScrollLines"变量指向一个unsigned integer值,其中包含滚轮旋转时暗示的行数:
- 如果为0,则没有滚动。
- 如果值为WHEEL_PAGESCROLL, 可以认为是在滚动条上单击了一次,使得向上或向下翻页。
- 如果行数大于可见行,也应该解释为翻页操作。
滚动行数默认为3,如果要修改该值,可以通过控制面板中的鼠标属性来修改,操作系统用指定为SPI_SETWHEELSCROLLLINES的WM_SETTINGCHANGE消息到所有顶级窗口,然后就可以调用SystemParametersInfo得到新的滚动行数了:
SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, pulScrollLines, 0)
控制滚动
下表中包含了可以提供滚动的控件(其中包含用户设置的可滚动行):
| 控件 | 滚动 |
|---|---|
| Edit Control | 垂直、水平 |
| List box Control | 垂直、水平 |
| Combo box | 没有下拉列表时,每次向前或向后滚动,有下拉列表时,每次滚动都把消息转寄给列表框,从而实现滚动。 |
| CMD (命令行) | 垂直 |
| Tree View | 垂直、水平 |
| List View | 垂直、水平 |
| Up/down Scrolls | 一次一个item |
| Trackbar Scrolls | 一次一个item |
| Microsoft Rich Edit 1.0 | 垂直,注意,Exchange客户端有自己的list view、treeview控件,因此不支持滚轮。 |
| Rich Edit 2.0 | 自从Microsoft Office 97 |
检测鼠标是否带滚轮
要确定鼠标是否带滚轮,可以调用GetSystemMetrics(SM_MOUSEWHEELPRESENT),如果返回TRUE就说明带。
下面多行编辑器控件的窗口处理过程示例:
BOOL ScrollLines(
PWNDDATA pwndData, //scrolls the window indicated
int cLinesToScroll); //number of times
short gcWheelDelta; //wheel delta from roll
PWNDDATA pWndData; //pointer to structure containing
//info about the window
UINT gucWheelScrollLines=0;//number of lines to scroll
//on a wheel rotation
gucWheelScrollLines=
SystemParametersInfo(SPI_GETWHEELSCROLLLINES,
0,
pulScrollLines,
0);
case WM_MOUSEWHEEL:
/*
* Don't handle zoom and datazoom.
*/
if (wParam & (MK_SHIFT | MK_CONTROL)) {
goto PassToDefaultWindowProc;
}
gcWheelDelta -= (short) HIWORD(wParam);
if (abs(gcWheelDelta) >=
WHEEL_DELTA && gucWheelScrollLines > 0) {
int cLineScroll;
/*
* Limit a roll of one (1) WHEEL_DELTA to
* scroll one (1) page.
*/
cLineScroll = (int) min(
(UINT) pWndData->ichLinesOnScreen - 1,
gucWheelScrollLines);
if (cLineScroll == 0) {
cLineScroll++;
}
cLineScroll *= (gcWheelDelta / WHEEL_DELTA);
assert(cLineScroll != 0);
gcWheelDelta = gcWheelDelta % WHEEL_DELTA;
return ScrollLines(pWndData, cLineScroll);
}
break;
MSH_MOUSEWHEEL消息
Windows 95, Windows NT 3.51:通过一个单独运行的模块MSWheel提供滚轮支持,它可以产生MSH_MOUSEWHEEL消息。MSWheel模块,由MSWheel.exe及MSWheel.dll组成,是安装IntelliMouse pointing device时包含在其软件部分中的。MSH_MOUSEWHEEL是在Zmouse.h中作为一个字符串定义的。
应用程序调用 RegisterWindowMessage以产生消息ID,带此ID的一个消息就会通过MSWhell投递给当前滚轮滚动的那个前台窗口。RegisterWindowMessage函数用来产生一个唯一的新窗口消息值,当调用SendMessage或PostMessage函数时就会用到该值。头部文件(ZMouse.h)包含了传给RegisterWindowMessage的串。
通过MSWheel模块检测滚轮是否存在
要确定滚轮是否可用,可以使用HwndMsWheel inline函数,或发送一个请求给MSWheel模块。Zmouse.h中可以找到HwndMsWheel,它不仅返回滚动行数,也注册消息、到MSWheel窗体的句柄,是否支持滚轮的标志。如果发送请求给MSWheel模块,如果应答为TRUE,就说明有滚轮。应用程序可以添加以下代码段以发送请求:
#include zmouse.h
HWND hdlMSHWheel=NULL;
UINT msgMSHWheelSupportActive=NULL;
BOOL fWheelSupport=FALSE;
msgMSHWheelSupportActive =
RegisterWindowMessage(MSH_WHEELSUPPORT);
hdlMSHWheel = FindWindow(MSH_WHEELMODULE_CLASS,
MSH_WHEELMODULE_TITLE);
if (hdlMSHWheel && msgMSHWheelSupportActive)
{
fWheelSupport = (BOOL)SendMessage(hdlMSHWheel,
msgMSHWheelSupportActive,
0,
0);
}
处理MSH_MOUSEWHEEL消息
通过使用GetForegroudWindow函数返回的窗口句柄,MSWheel模块可以把滚轮消息投递给前台窗口。前台窗口必须决定是否处理该消息,或交给支持滚轮的控件或内置OLE对象处理。
如果前台窗口需要传递滚轮消息,它可以使 用PostMessage 或SendMessage来实现。对于内置支持滚轮的控件,你必须决定是否应用程序应该使用SendMessage函数并判断返回值。
对于内置的OLE应用程序来说,请使用PostMessage。 由内置OLE的运行模式决定没有必要检查返回值,因为容器把消息提交给服务器,然后就会“忘记”该消息,由服务器应用程序决定是否处理。
对于OLE服务器来说(包括文档类服务器),把处理滚轮消息的代码交给窗口处理过程,当传递消息给内置的OLE应用程序时,建议通过 IOleInPlaceObject:GetWindow得到相应的窗口句柄。
内置应用程序必须确保处理了MSH_MOUSEWHEEL消息,尤其需要注意的是,应用程序是内置的时,界面不会在frame窗口呈现,所以处理消息的代码是在frame窗口的处理过程中的话,消息不会被处理。例如,用Microsoft Word及Microsoft Excel时,由于文档窗口就是最高层的内建窗口,因此那也是需要处理消息的地方。
通过MSWheel模块确定滚动行数
通过在IntelliPoint的滚轮设置中,可以设置每次滚动(一个槽口)所滚动的行数,或者控制面板的鼠标属性中可以设置。
要得到当前设置的行数,可以使用以下代码请求MSWheel模块:
#include "zmouse.h"
HWND hdlMSHWheel=NULL;
UINT msgMSHWheelGetScrollLines=NULL;
UINT uiMsh_WheelScrollLines;
msgMSHWheelGetScrollLines =
RegisterWindowMessage(MSH_SCROLL_LINES);
hdlMSHWheel = FindWindow(MSH_WHEELMODULE_CLASS,
MSH_WHEELMODULE_TITLE);
if (hdlMSHWheel && msgMSHWheelGetScrollLines)
{
uiMsh_WheelScrollLines =
(UINT)SendMessage(hdlMSHWheel,
msgMSHWheelGetScrollLines,
0,
0);
}
另外,也可以使用内联函数HwnMsWheel,ZMouse.h包含其函数声明,该函数不仅返回滚动行数,而且还包括已注册的消息、MSWheel窗口的句柄、支持滚轮的标志。
如果变更了滚动行数,MSWheel就会调用以下代码通过广播把消息传给所有窗体:
SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETWHEELSCROLLLINES, NULL);
当一个应用程序收到该消息后,就会向MSWheel模块发送一个消息,以得到滚动行数:
SendMessage(hdlMSHWheel, msgMSHWheelGetScrollLines, 0, 0).
当设置滚动行数时,用户可以选择滚动一页,而不一定非得指定滚动行数,如果是这样的话,就会用到WHEEL_PAGESCROLL,如果返回该值,滚动操作应该像每次单击滚动条时一样滚动一页。roll one page at a time.
滚动行函数在MSWheel发行版019中提供完备的支持。
窗口激活
当用户单击一个非激活的顶级窗体,或非激活的顶级窗体的子窗体时,系统就会发送 WM_MOUSEACTIVATE消息(还包括其他消息)给顶级窗体或子窗体,该消息在WM_NCHITTEST消息之后,但在button-down消息之前。当把 WM_MOUSEACTIVATE消息交给DefWindowProc函数处理时,系统激活该顶级窗口并投递button-down消息。
通过处理WM_MOUSEACTIVATE,一个窗体可以就像鼠标单击一样控制激活顶级窗口,并确定该窗体是否接收后续的button-down消息。处理WM_MOUSEACTIVATE后,通过返回以下值实现该目的:
| 值 | 含义 |
|---|---|
| MA_ACTIVATE | 激活窗体,但不删除鼠标消息。 |
| MA_NOACTIVATE | 不激活窗体,也不删除鼠标消息。 |
| MA_ACTIVATEANDEAT | 激活窗体,删除鼠标消息。 |
| MA_NOACTIVATEANDEAT | 不激活窗体,但删除鼠标消息。 |
原文:见MSDN
© 2003 Microsoft Corporation. All rights reserved.
翻译:Room3rd@hotmail.com
本文围绕Windows系统的鼠标输入展开,介绍了鼠标光标、捕获、单击锁等设置,阐述了鼠标消息分类,包括客户区域和非客户区域消息及相关参数、双击消息等,还讲解了鼠标滚轮消息处理,如WM_MOUSEWHEEL和MSH_MOUSEWHEEL消息,以及窗口激活时的消息处理。
344

被折叠的 条评论
为什么被折叠?



