关于鼠标输入
鼠标是应用程序的一个重要的但又是可选的用户输入设备.一个写得很好的应用程序应该包括鼠标接口,但它不应该单独依靠鼠标来获得用户输入.应用程序应该同样提供全部的键盘支持.
应用程序以发送或提供交给它的窗的消息的形式来接收鼠标输入.
此段含盖了下列的主题:
鼠标光标
鼠标捕获
鼠标点击锁定
鼠标配置
XBUTTONs
鼠标消息
鼠标声纳
鼠标消失
鼠标滚轮
窗口激活
当用户移动鼠标时,系统会在屏幕上移动一个叫作鼠标光标的位图.鼠标光标包含了一个单像素点,此点叫作热点.系统会跟踪它并且会把它认为是光标的位置.当一个鼠标事件发生,包含热点的窗口一般会收到此事件引发的鼠标消息.此窗口不需要被激活或者具有焦点以接收鼠标消息.
系统维持了一个控制鼠标速度的变量,那就是当用户移动鼠标时光标移动的距离.你可以使用SystemParametersInfo函数,flag为SPI_GETMOUSE 或者SPI_SETMOUSE 的参数来获得或者设置鼠标速度.更多关于鼠标光标的信息,请看光标.
当一个鼠标事件发生时,系统一般会提交一个鼠标消息给包含光标热点的窗口.应用程序可以改变这种行为,如使用SetCapture函数发送鼠标消息给指定的窗口.窗口会接收所有的消息直到应用程序调用ReleaseCapture函数或指定另一个捕获窗口,或直到用户点击由另一个线程创建的窗口.
当鼠标捕获改变时,系统发送一个WM_CAPTURECHANGED 消息给正失去鼠标捕获的窗口.消息的 lParam 参数指定了正获得鼠标捕获的窗口的句柄.
仅仅前台(foreground)窗口能够捕获鼠标输入.当后台(background)窗口尝试捕获鼠标输入时,它仅仅会收到光标热点位于窗口的可视部份时发生的鼠标事件的消息
如果窗口必须接收所有的鼠标输入,捕获鼠标输入是有用的,即使光标移到了窗口的外部.例如,在鼠标按钮被按下的事件发生时,应用程序一般会跟踪光标的位置,跟随光标直到鼠标按钮弹起的事件发生.如果应用程序还没有捕获鼠标输入并且用户在窗口外面释放了鼠标按钮,则窗口不会收到按钮弹起的消息.
线程使用GetCapture 函数来确定它是否有窗口捕获到了鼠标.如果线程的窗口中有已捕获到了鼠标, GetCapture 会得到窗口的句柄.
鼠标ClickLock 附加功能特性已被加入到Microsoft Windows Millennium Edition (Windows Me) 和 Windows XP中(译者注:控制面板->鼠标->按钮->点击锁定,可打开此功能). 这个特性可在一次单击后让用户锁住最初所按的鼠标按钮.对于应程程序,按钮仍然会出现以被按下.对于未锁定的按钮,应用程序会发送任意的鼠标的消息或者用户能够点击任意的鼠标按钮.这个特性使用户做一个复杂的鼠标组合变得更简单.例如,有某种物理限制的能高亮显示文本,拖动目标,或者更容易地打开菜单.更多信息,请看下列标记(flag)和SystemParametersInfo的备注:
SPI_GETMOUSECLICKLOCK
SPI_SETMOUSECLICKLOCK
SPI_GETMOUSECLICKLOCKTIME
SPI_SETMOUSECLICKLOCKTIME
虽然鼠标是应用程序的重要输入设备,但是未必每个用户都有鼠标.程用程序可通传递值SM_MOUSEPRESENT 给函数GetSystemMetrics来确定系统是否有鼠标.
Windows 支持具有三个按钮的鼠标.在三键鼠标上,按钮是这样指派的:左键,中键,右键.消息和与鼠标有关的指定常量使用字母L, M和R 来识别按钮.单键的鼠标按钮则被认为是左键.虽然Windows 支持多键鼠标,但是大多数应用程序主要使用左键,使用其它键的时候很少,或根本不用.
从Windows 98和Microsoft Windows NT 4.0开始,应用程序也能支持鼠标滚轮.鼠标滚轮可按下,也可滚动.当鼠标滚轮被按下时,它就作为中键(第三键)发送标准的中键消息给你的应用程序.当它滚动时,会发送滚轮消息给应用程序.更多信息,请看The Mouse Wheel 节.
从Windows 2000开始,应用程序能够支持应用程序命令按钮.这些按钮叫X按钮,允许用户更容易地访问因特网浏览器,E-mail,媒体服务等.当按下X按钮时,会发送 WM_APPCOMMAND消息给你的应用程序.更多信息,请看WM_APPCOMMAND消息的描述.
应用程序可以确定鼠标按钮的个数,通过传值 SM_CMOUSEBUTTONS 给函数 GetSystemMetrics 即可.要为左瞥子的用户设置鼠标,应用程序可使用SwapMouseButton函数来反置左右鼠标键的功能.另一种反置按钮功能的方式是传值 SPI_SETMOUSEBUTTONSWAP给函数 SystemParametersInfo .然而,要注意鼠标是共享资源,反置鼠标按钮的功能会影响所有的应用程序.
从Windows 2000开始,Microsoft 支持 Microsoft IntelliMouse Explorer.它是一个具有五个按钮的鼠标.除了左中右按钮,还有XBUTTON1和 XBUTTON2.在使用IE时,这两按钮提供后退和前进的导航功能.
窗口管理器通过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_APPCOMMAND 消息给它的父窗口.这与这种方式相似:右击时,会调用上下文菜单--DefWindowProc 会发送WM_CONTEXTMENU消息给菜单和它的父窗口.此外,如果DefWindowProc 收到顶级窗口的WM_APPCOMMAND 消息,它会使用代码HSHELL_APPCOMMAND,调用壳钩子.
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消息.
客户区鼠标消息的lParam 参数指示了光标热点的位置.低序(low-order)字指示了热点的x坐标,高序(high-order)字指示了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_SETDOUBLECLKHEIGHT标记给SystemParametersInfo函数,系统使用此矩形来侦测双击. 然而,要注意设置双击超时值和此矩形会影响所有的应用程序.
定义的应用程序窗口默认是不接收双击消息.由于系统开销涩及到生成双击消息,仅会为属于CS_DBLCLKS类风格的窗口生成这些消息. 当注册窗口类时,你的应用程序必须设置这个风格.更多信息,请看Window Classes.
双击消息总是四消息系列中的第三个消息.前两消息是第一次点击产生的键按下和键弹起消息.第二次点击生成双击消息,这之后是另一个键弹起消息.例如,双击鼠标左键生成如下的消息序列:
WM_LBUTTONDOWN
WM_LBUTTONUP
WM_LBUTTONDBLCLK
WM_LBUTTONUP
因为窗口在收到双击消息之前,总是收到键按下消息,应用程序一般在键按下消息期间,使用双击消息来扩展窗口开始的任务.例如,当用户在微软画图程序的调色板中点击某颜色时,画图程序会在调色板旁显示选中的颜色.当用户双击某颜色时,画图程序会显示此颜色并打开颜色编辑对话框.
当鼠标事件发生在窗口除了客户区的任意区域,窗口会收到非客户区鼠标消息.窗口的非客户区由窗口边界、菜单栏、标题栏、滚动条、窗口菜单、最小化按钮和最大花按钮组成.
系统生成非客户区消息主要是为系统自已使用.例如,当光标热点移到窗口的边界时,系统使用非客户区消息将光标改变成双头箭头.窗口必须传递非客户区鼠标消息给DefWindowProc 函数,以利用内建的鼠标接口.
每个客户区鼠标消息都有一个相应的非客户区鼠标消息. 除了指定的非客户区消息常量,包括字母NC,这些消息的名称是相似的. 例如,在非客户区中移动光标会生成WM_NCMOUSEMOVE消息,并且在非客户区中按下鼠标左键会生成WM_NCLBUTTONDOWN消息.
非客户区鼠标消息的 lParam 参数是一个结构,它包含了光标热点的x轴 和 y轴坐标.与客户区鼠标的坐标不同,这个坐标是屏幕中指定的某坐标,而不是客户坐标.在屏幕坐标系中,所有屏幕上的都是相对于屏幕左上角的坐标 (0,0).
wParam 参数包含了点击测试值, 这个值指示了鼠标事件在非客户中发生的地方.下节解释了点击测试的目的.
无论鼠标事件什么时候发生,系统会发送WM_NCHITTEST 消息要么给包含光标热点的窗口要么给已捕获鼠标的窗口.系统使用此消息来确定是发送客户区鼠标消息还是非客户区鼠标消息.必须接收鼠标移动和鼠标按钮消息的应用程序必须传递WM_NCHITTEST 消息给 DefWindowProc 函数s.
WM_NCHITTEST消息的 lParam 参数包含了光标热点的屏幕坐标. DefWindowProc 函数检查坐标并返回点击测试值,这个值指示了热点的位置.点击测试值可以是下列值之一.
值 | 热点的位置 |
HTBORDER | 在没有缩放边框窗口的边界中. |
HTBOTTOM | 在窗口的下部水平边界中. |
HTBOTTOMLEFT | 在窗口边界左下角中. |
HTBOTTOMRIGHT | 在窗口边界右下角中. |
HTCAPTION | 在标题栏中. |
HTCLIENT | 在客户区中. |
HTCLOSE | 在关闭按钮中. |
HTERROR | 在屏幕背景上,或在窗口间的分界线上 (与HTNOWHERE相同,除了 DefWindowProc 函数产生一个系统嘟嘟的错误声). |
HTGROWBOX | 大尺寸框中 (与HTSIZE相同). |
HTHELP | 在帮助按钮中. |
HTHSCROLL | 在水平滚动条中. |
HTLEFT | 在窗口左边界中. |
HTMENU | 在菜单中. |
HTMAXBUTTON | 在最大化按钮中. |
HTMINBUTTON | 在最小化按钮中. |
HTNOWHERE | 在屏幕背景上或在窗口分界线上. |
HTREDUCE | 在最小化按钮中. |
HTRIGHT | 在窗口的右边界. |
HTSIZE | 在尺寸框中 (与HTGROWBOX相同). |
HTSYSMENU | 在系统菜单或在子窗口的关闭按钮. |
HTTOP | 在窗口的上部水平边界中. |
HTTOPLEFT | 在窗口边界的左上角. |
HTTOPRIGHT | 在窗口边界的右上角. |
HTTRANSPARENT | 在当前被相同线程的中另一窗口覆盖的窗口. |
HTVSCROLL | 在垂真滚动条. |
HTZOOM | 在最大化按钮. |
如果光标在窗口的客户区中, DefWindowProc 会返回HTCLIENT 点击测试值给窗口程序.当窗口程序把这个代码返回给系统,系统会将光标的屏幕坐标转换为客户坐标,然后提交适当的客户区鼠标消息.
当光标热点位于窗口的非客户区时,DefWindowProc 函数返回其它点击测试值中的一个.当窗口程序返回这些点击值之一时,系统会提交非客户区鼠标消息.非客户区鼠标消息把点击测试值放入到消息的wParam 参数中,将光标坐标放到lParam 参数中.
鼠标声纳辅助工具特性已被添加到Windows Me 和Windows XP. 当用户按下并释入CTRL键时,这个特性短暂地显示了几个绕着指针的同心圆.这个特性帮助用户定位屏幕上的鼠标指针,如屏幕很乱、分辨率高、显示器质量不好或者用户的视力不好.更多信息,请看SystemParametersInfo 的中下列标记:
SPI_GETMOUSESONAR
SPI_SETMOUSESONAR
鼠标消失辅助功能特性已被添加到 Windows Me 和Windows XP. 这个特性可在用户正进行输入时隐藏鼠标指针.这个特性可以防止鼠标指针混淆正输入的文本.例如,在E-mail或其它文档中.更多信息,请看SystemParametersInfo 中的下列标记:
SPI_GETMOUSEVANISH
SPI_SETMOUSEVANISH
鼠标滚轮融合了滚轮和鼠标按钮的特性.鼠标滚轮有分散的间距均匀的刻痕.当你转动滚轮的时候就会遇到刻痕,滚轮消息就会被发送到你的应用程序.滚轮按钮也可以像标准的Windows 中键 (第三个键)那样操作.按下并释放鼠标滚轮会发送标准的WM_MBUTTONUP 和 WM_MBUTTONDOWN 消息.双击这个第三键会发送标准的WM_MBUTTONDBLCLK 消息.
Windows 95, Windows NT 3.51: 通过MSH_MOUSEWHEEL消息支持鼠标滚轮,此消息作为分散模型的部分,以及随之而来的IntelliMouse定点设备.
Windows 98/Me, Windows NT 4.0 and later: 通过WM_MOUSEWHEEL 消息支持鼠标滚轮.
在大多数情况下,应用程序明显地处理 WM_MOUSEWHEEL 和 MSH_MOUSEWHEEL .然而, MSH_MOUSEWHEEL 和 WM_MOUSEWHEEL 在以下的重要方式中是不同的:
MSH_MOUSEWHEEL没有fwkeys .
MSH_MOUSEWHEEL 包装了 zDelta 参数,这与WM_MOUSEWHEEL是不同的.
DefWindowProc 函数没有对MSH_MOUSEWHEEL作过任何特别的处理.
WM_MOUSEWHEEL 消息首先转到焦点控件再通过DefWindowProc函数被转寄到父窗口. MSH_MOUSEWHEEL 消息首先转到最外层的父窗口,并且必须通过应用程序被转寄到焦点控件.
当应用程序处理WM_MOUSEWHEEL 消息时,它必须返回零.当应用程序处理 MSH_MOUSEWHEEL 消息时,它必须返回TRUE.
以下各节概述了每个消息是怎被处理的.
WM_MOUSEWHEEL 消息
MSH_MOUSEWHEEL消息
Windows 98/Me, Windows NT 4.0 以及后续系统: 通过WM_MOUSEWHEEL 消息提供鼠标滚轮转动的支持.
滚动鼠标滚轮会发送WM_MOUSEWHEEL 消息给焦点窗口. DefWindowProc 函数再将这个消息传给窗口的父窗口.不应该有内部转发的消息,因为DefWindowProc 会把它传给上面的父窗口链,直到窗口处理它被发现.
确定滚动的行数
应用程序应该使用 SystemParametersInfo 函数,来获得每次滚动操作(滚轮刻痕)文档所滚动的行数.要获得这个行数,应用程序可进行如下的调用:
SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, pulScrollLines, 0)
变量"pulScrollLines" 指向一个无符号的整型值.当鼠标滚轮滚动时没有修饰键时,这个值接收滚动的建议(suggested)行数:
如果行数为0,没有滚动事件发生.
如果行数是WHEEL_PAGESCROLL, 滚轮转动应该解释为点击了一次滚动条的下一页或上一页.
如果滚动的行数大于所能看见的行数,滚动操作应该解释为下一页或上一页.
滚动行数的默认值是3.如用户在控制面板中的鼠标属性卡中改变了滚动的行数,操作系统会使用指定的SPI_SETWHEELSCROLLLINES,广播WM_SETTINGCHANGE 消息给所有的顶级窗口.当应用程序接收到WM_SETTINGCHANGE 消息,它可使用下面的调用获得新的滚动行数:
SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, pulScrollLines, 0)
能滚动的控件
下表列出了有滚动功能的控件(包括用户设置滚动行数).
控件 | 滚动 |
编辑控件 | 垂直和水平. |
列表框控件 | 垂直和水平. |
组合框 | 当没有下拉时,每个滚动栏会获得下一项或前一项.当下拉时,每个滚动栏会转发消息给列表框,列表框也就相应地进行滚动. |
CMD (命令行) | 垂直. |
Tree View | 垂直和水平. |
List View | 垂直和水平. |
Up/down Scrolls | 一次滚动一项. |
Trackbar Scrolls | 一次滚动一项. |
Microsoft Rich Edit 1.0 | 垂直.注意,Exchange客户端有自己的不支持滚轮的list view 和tree view 控件的版本. |
Rich Edit 2.0 | 来自 Microsoft Office 97. |
侦测带滚轮的鼠标
要确定滚轮鼠标是否连接上,可调用 GetSystemMetrics(SM_MOUSEWHEELPRESENT). 返回值为TRUE 表明是连上的.
下面的例子来自一个多行的编辑控件的窗口程序:
示例
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: 通过单独运行模块和产生MSH_MOUSEWHEEL 消息的MSWheel,来提供对鼠标滚轮的支持.MSWheel 模块由MSWheel.exe 和MSWheel.dll组成,随着Microsoft IntelliPoint软件被安装. IntelliPoint软件对IntelliMouse定点设备的提供支持. MSH_MOUSEWHEEL 在头文件Zmouse.h中被定义为字符串.
应用程序调用RegisterWindowMessage 生成消息ID.当滚轮转动时,带有这种ID的消息由MSWheel提交给当前的前台窗口.RegisterWindowMessage 定义了唯一的窗口消息号.当调用SendMessage或PostMessage函数时,就可使用返回的消息值.头文件(ZMouse.h) 包含了传递给RegisterWindowMessage 的字符串.
注意 Switch语句的case子句要求常量,而滚轮消息是变量.然而,你可在If语句中检查MSH_MOUSEWHEEL .
侦测带有 MSWheel 模块的鼠标滚轮
要确定鼠标滚轮是否可用,应用程序可使HwndMsWheel 内联函数或它发送一个查询给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);
}
处理SH_MOUSEWHEEL 消息
通过使用GetForegroundWindow返回的窗口名柄, MSWheel模块提交滚轮消息给前台窗口.前台窗口必须决定是否响应消息或者把它传给任意的有滚轮功能的控件,或者激活嵌入的OLE对象.
如果前台窗口需要传播滚轮消息,它可使用PostMessage 或者 SendMessage.对于嵌有滚轮功能的控件,你必须决定应用程序是否使用SendMessage 函数和检查返回值.
对于嵌有OLE 的应用程序,可使用PostMessage. 这里无需检查返回值,因为嵌有OLE的应用程序的模型是容器发送消息给服务器,然后忘记它.它取决于服务端应用程序是否采取动作.
对于OLE 服务器(包括文档对象服务器),把处理滚轮消息的代码放在获得嵌入式窗口的窗口过程中.当把消息传递给嵌有OLE的应用程序时,获取适当窗口的推荐调用是IOleInPlaceObject:GetWindow.
嵌入式应用程序必须确保处理MSH_MOUSEWHEEL 消息的代码出现在它返回IOleInPlaceObject:GetWindow 调用的窗口过程中. 具体来说,当应用程是嵌入时,要注意框架窗口是不出现的.因此,如果处理消息的代码在框架窗口的中窗口过程中,则此消息是不会被处理的.例如,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);
}
作为一种替代方法,应用程序可以使用内联函数HwndMsWheel, 可在ZMouse.h中找到它. 这个内联函数不仅返回滚动的行数,还返回注册的消息、MSWheel 窗口的句柄和滚轮鼠标支持的标记.
如果用户改变滚动的行数,可使用下面的调用,让MSWheel 广播消息给所有的窗口:
SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETWHEELSCROLLLINES, NULL);
当应用程序收到这个消息,它则会使用SendMessage(hdlMSHWheel, msgMSHWheelGetScrollLines, 0, 0)发送消息给MSWheel模块以获得滚动的行数.
注意 WM_SETTINGCHANGE与WM_WININICHANGE是等价的. SDK 文档指明了Windows NT 3.51不支持 WM_SETTINGCHANGE ,但是在所有的操作系统中,MSWheel 将使用上面描述的语法.
当设置滚动的行数时,用户能选择一次滚动一页,来替代具体的行数.在那种情况下,使用定义的值 WHEEL_PAGESCROLL. 如果这是返回值,执行的操作应等价于用户点击滚动条而引起的一次滚动一页.
滚动行功能在MSWheel的发布版019中完全可用.
当用户点击非活动窗口或非活动的顶级窗口的子窗口时,系统会发送WM_MOUSEACTIVATE消息(包括其它消息)给顶级或子窗口.系统在提交WM_NCHITTEST消息给窗口后,但又在提交按钮按下消息之前,发送这个消息.当把WM_MOUSEACTIVATE 消息传递给DefWindowProc 函数时,系统时会激活顶级窗口,然后提交按钮按下消息给顶级窗口或子窗口.
通过处理WM_MOUSEACTIVATE, 窗口能够控制顶级窗口由于点击是否成为活动窗口,和控制被点击的窗口是否接收随后的按钮按下消息.在处理WM_MOUSEACTIVATE后,返回下列值之一就可这样做了.
值 | 含义 |
MA_ACTIVATE | 激活窗口且不丢弃鼠标消息. |
MA_NOACTIVATE | 不激活窗口且不丢弃鼠标消息. |
MA_ACTIVATEANDEAT | 激活窗口且丢弃鼠标消息. |
MA_NOACTIVATEANDEAT | 不激活窗口且丢弃鼠标消息. |