当前位置:首页 > VB 钩子详解
Static Hookstruct As KBDLLHOOKSTRUCT If (Code = HC_ACTION) Then
Call CopyMemory(Hookstruct, ByVal lParam, Len(Hookstruct))
If (IsHooked(Hookstruct)) Then KeyboardCallback = 1 Exit Function End If
End If
KeyboardCallback = CallNextHookEx(KeyboardHandle, _ Code, wParam, lParam)
End Function
函数KeyboardCallback,是整个钩子函数的核心,
参数1:Code,表示拦截层次,之前我们已经说过,如果Code为0,则拦截所有窗口的键盘输入。
参数2:wParam表示是何种Windows消息
参数3:lParam表示某条Windows消息的具体内容的指针,它实际指向存储那个内容的内存地址。
下面详细叙述关于wParam和lParam:
wParam和lParam是Windows消息机制的两个最重要参数,整个Windows依靠这两个参数传递各种各样的消息,首先是wParam,它表示此次的消息类型是什么?是键盘?是鼠标?键盘里又分按下还是抬起,鼠标里又分是单击还是双击,等等。lParam是一个指针,它指向本条消息所存储的信息的内存区域的首地址,很显然,这个地址存放的东西是很灵活的,比如鼠标消息,那么这里可能存放的是各键的状态或者光标的X,Y座标。换成键盘消息,则是键码等等。总之,wParam区分了类别,lParam存放了该类别所存储的信息。因为VB没有指针,好在这里并不需要更多的指针妈作,只是记录一个首地址,所以可以用Long来代替。 注:在本程序里,wParam始终为256和257,257表示抬起键盘,256表示按下键盘,lParam每次运行都不一定一样,因为每次系统重启Windows都会重新定义消息指针,但是就一次进入而言,这个值是不会改变的,退出之后再进就有可能发生变化了。
Static Hookstruct As KBDLLHOOKSTRUCT
定义一个局部静态结构体实例,结构体为KBDLLHOOKSTRUCT。
If (Code = HC_ACTION) Then
Call CopyMemory(Hookstruct, ByVal lParam, Len(Hookstruct))
If (IsHooked(Hookstruct)) Then KeyboardCallback = 1 Exit Function End If
End If
If Code=HC_ACTION,这条鉴别Windows的消息来源,实际上我们之前已经将HC_ACTION定义为0了,所以所有键盘消息都将从此通过,那么,这个鉴别的意义何在呢?因为有可能还有别的键盘拦截程序等待着这些消息,我们不应该将这些消息据为己有,而是该交还给系统。
Call CopyMemory(Hookstruct, ByVal lParam, Len(Hookstruct))
这里用到了CopyMemory,作用是将lParam地址的内容复制到本地变量Hookstruct里来,这里又是VB的一个弊端,因为没有指针,所以必须动用到CopyMemory来完成这个使命。
If (IsHooked(Hookstruct)) Then KeyboardCallback = 1 Exit Function End If
IsHooked是我们自己定义的一个函数,该函数过滤了我们不希望出现的键盘码,比如说我们现在就是要不允许用户输入A,那么就可以在IsHooked里将A吞噬掉,那么键盘就永远打不出A来了。该函数返回0或者1,1表示此键确为我们不想要的字符,那么吃掉这条消息,不将它交还系统,Exit Function直接退出函数。如果不是,则略过。
可以看到,在If语句的最后是:
KeyboardCallback = CallNextHookEx(KeyboardHandle, _ Code, wParam, lParam)
表示:如果前面的条件都不成立,那么说明这条消息并非我们需要的消息,此时我们将此消息释放,用CallNextHookEx交还给系统。
下面我们进行前面提到的IsHooked函数的定义,这个函数主要是过滤我们不想要的那些键或者键盘组合,这里我们屏蔽了Alt+TAB组合:
Public Function IsHooked(ByRef Hookstruct As KBDLLHOOKSTRUCT) _ As Boolean
If (KeyboardHook Is Nothing) Then IsHooked = False Exit Function End If
有时候CopyMemory也会发生意想不到的事情,所以,当KeyboardHook = Nothing (无值)的情况下,退出,略过该函数,以防不可预知的错误。
If (Hookstruct.vkCode = VK_TAB) And _ CBool(Hookstruct.flags And _ LLKHF_ALTDOWN) Then
IsHooked = True Exit Function End If
以上拦截了Alt+Tab的键盘组合,并将IsHooked返回True(就是1),表示本次按键确实符合了过滤原则,应该吞吃掉。
End Function
最后一步,释放钩子函数:
Public Declare Function UnhookWindowsHookEx Lib \ (ByVal hHook As Long) As Long
Public Sub UnhookKeyboard() If (Hooked) Then
Call UnhookWindowsHookEx(KeyboardHandle) End If End Sub
这个函数很简单,使用UnhookWindowsHookEx这个API释放之前由SetWindowsHookEx所定制的钩子函数。
一般而言,我们将钩子函数的创建放在窗体的Load部分,表示一进入程序立即启动钩子,而释放钩子则放在UnLoad部分,表示一旦程序关闭,我们需要立刻释放钩子所占用的资源。
结束语:
事实上,该例子演示了整个键盘拦截和屏蔽的功能,如果仅仅是需要知道用户按下了什么键,那么IsHooked函数是不需要的,并且我们也没有必要吞噬任何消息,只是让消息从我们的钩子函数里过一遍,知道它的值,然后再将此消息交还给系统即可,那样的话,程序将会更
加简单。另外,在调试这类超越了VB编译环境本身的API程序时必须注意存盘,不断地存盘,因为VB环境和这些API函数同属系统级,因此它无法管理这些API,一旦出现问题,整个VB环境会在毫无预知的情况下造成全线崩溃的局面(比如VB编译环境的界面不提示任何内容自己就莫名其妙地突然消失等等),所以在按下RUN之前一定要记得存盘!!
共分享92篇相关文档