使用“钩子”实现快捷键控制鼠标

技术与开发

钩子(Hook),是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的。当消息到达后,在目标窗口处理函数之前处理它。

钩子机制允许应用程序截获处理Windows消息或特定事件。每当特定的消息发出,在没有到达目的窗口前,钩子程序就先捕获该消息,亦即钩子函数先得到控制权。这时钩子函数既可以加工处理(改变)该消息,也可以不作处理而继续传递该消息,还可以强制结束消息的传递。下面我们就以设计一个快捷键控制鼠标开关的程序为例,来看看钩子的妙用。

设计思路:理论上若想彻底停用鼠标,可以从禁用中断着手,可是实际操作起来就比较麻烦了,实现起来代码也比较复杂。一是因为鼠标使用的端口有PS/2、USB等等,用到的中断不尽相同;二是因为在Windows操作系统下,程序对中断的控制并不像DOS下那样随意。

想达到目的,并不一定非要通过禁用中断那么彻底,只要拦截所有鼠标传给Windows的消息即可,这实现起来就相对容易得多,利用钩子就完全可以做到。

在程序中,需要设置两个钩子,一个是键盘钩子,用以监视我们设为开关的F12键;一个是鼠标钩子,用以控制启用/停用鼠标。在用户按下F12键的时候,根据鼠标当前状态(启用/停用)采取相应的操作(停用/启用鼠标)。

第一步:程序初始化阶段,既然是开关控制,就要设置一个标志变量,用来存放鼠标当前状态,该变量值初始为1(即表示鼠标处于启用状态);通过调用子程序1设置键盘钩子。

第二步:子程序1通过键盘钩子监视键盘事件,检测F12键是否被按下,如F12被按下则根据当前鼠标状态(启用/停用,具体操作中根据标志变量的值来判断),向主程序发送相应消息,并修改标志变量的值。

程序源代码:

程序由三个部分组成,分别为:

1.主程序,初始化数据,显示程序界面,还有向系统托盘添加图标的代码,在系统中添加一个钩子用以监视子程序1中传来的消息,根据传来的消息类型相应调用子程序2中的函数安装/卸载鼠标钩子,实现停用/启用鼠标的操作。关键代码如下:

invoke InstallHook,hWnd,WM_ HOOK;创建钩子,监视接收到的消息

……

.elseif uMsg==WM_HOOK ;如果拦截到消息

pushad ;所有寄存器进栈,保存数据,准备进行操作

mov eax,wParam

.if eax == 11111111h ;若子程序1发来的消息内容是11111111

invoke mouseInstallHook,hWnd,WM_mHOOK;装载子程序2中的鼠标钩子,即停用鼠标

.elseif eax == 22222222h;若子程序1发来的消息内容是22222222

invoke mouseUninstallHook ;卸载子程序2中的鼠标钩子,即启用鼠标

.endif

popad ;所有寄存器出栈,恢复数据,程序继续运行

.elseif uMsg==WM_DESTROY ;如果准备退出程序

invoke UninstallHook ;卸载主程序钩子

2.子程序1,键盘钩子代码,用来监视F12键是否按下,如果F12键按下,通过标志变量查看鼠标目前处于停用还是启用状态,相应地发送两种信息以便启用/停用鼠标,达到开关的目的。关键代码如下:

HookProc proc _dwCode,_wParam,_lParam

invoke CallNextHookEx,hHook,_dwCode,_wParam,_lParam

pushad ;所有寄存器进栈,保存数据,准备进行操作

mov eax,_lParam;子程序1收到键盘消息后,将扫描码消息放在寄存器eax中

.if eax == 00580001h ;如果是F12键被按下,eax中的值应为00580001h,通过此句判断按下的是否为F12键

.if mark == 1 ;如果mark为1(即鼠标目前处于启用状态)

mov mark,0 ;如果F12键被按下,而且鼠标此时处于启用状态,则把mark置0

invoke PostMessage,hWnd,dwMessage,11111111h,NULL

;向主程序发送内容为11111111的消息,让主程序准备停用鼠标

.elseif mark==0;如果F12键按下的时候, mark为0(即鼠标目前处于停用状态)

mov mark,1 ;mark置1

invoke PostMessage,hWnd,dwMessage,22222222h,NULL

;向主程序发送内容为22222222的消息,让主程序准备启用鼠标

3.子程序2,鼠标钩子代码,用来实现启用/停用鼠标的具体操作。关键代码如下:

mouseInstallHook proc _hWnd,_dw Message;主程序调用这一函数来停用鼠标

invoke SetWindowsHookEx,WH_MOUSE_LL,addr mouseHookProc,hInstance,NULL ;钩子不是WH_MOUSE而是WH_MOUSE_LL,否则极易死机。

将上面三部分程序编译后,将生成一个主程序exe文件和两个dll文件。分别为msk.exe、hookdll.dll、mouse.dll。

程序的安装和使用

把这三个文件放在同一文件夹内,给主程序msk.exe在桌面或者任何便于操作的地方创建一个快捷方式,双击运行,程序初始会以最小化模式运行,并在桌面右下角的系统托盘内添加该程序的图标,这是为了不影响其他操作,鼠标经过图标时会显示“鼠标软开关”的字样。

在需要停用鼠标的时候,只要按一下F12键,试试看,鼠标是不是纹丝不动了?想要启用鼠标的时候,再按一下F12键就可以了。