如何在vba中使用Hook钩子?

Windows系统是消息处理机制的系统。在Windows系统内,任何的操作都是消息驱动的。

当我们按下一个键盘按键时,会发送一个键盘消息,这个消息首先会到钩子程序,然后再到对应的窗户程序。

钩子就是应用程序安装的一个用于监视消息的子程序,它可以在消息到达目标窗口的程序之前进行判断处理。

钩子有多种类型,不同类型的钩子可以监视不同类型的消息。

钩子还分成线程级的和全局级的,线程级的只能监视具体的线程的消息,全局的可以监视所有线程的消息。

一个可以监视、拦截特定消息的函数称为钩子程序(hook procedure)
在vba中使用钩子的一般步骤如下:

  1. SetWindowsHookEx函数安装特定类型的钩子到钩子链的最前端。
  2. 在特定类型的钩子程序中处理拦截的消息。
  3. UnhookWindowsHookEx函数卸载步骤1安装的钩子。

api函数SetWindowsHookEx是安装钩子的函数。

它的C++语法如下:

HHOOK WINAPI SetWindowsHookEx(
  _In_ int       idHook,
  _In_ HOOKPROC  lpfn,
  _In_ HINSTANCE hMod,
  _In_ DWORD     dwThreadId
);

其中参数idHook为要安装的钩子类型,参数lpfn为指向钩子程序的指针,hMod参数为要远程注入的DLL的句柄,dwThreadId参数为钩子程序要关联的线程ID。

它的vb语法如下:

Public Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" _
(ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, ByVal dwThreadId As Long) As Long

如果安装成功,SetWindowsHookEx函数将返回钩子程序的句柄,该句柄将被UnhookWindowsHookEx函数用于卸载。

以下是一个通用的在vba中使用钩子的代码结构:

Public hHook As Long
Public Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" _
(ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, ByVal dwThreadId As Long) As Long
Public Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long
Public Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, ByVal ncode As Long, ByVal wParam As Long, lParam As Any) As Long
Public Declare Function GetCurrentThreadId Lib "kernel32" () As Long
Const WH_KEYBOARD = 2
Sub BeginHK()
    '获取当前的线程ID
    i = GetCurrentThreadId
    '这里安装的是键盘钩子
    hHook = SetWindowsHookEx(WH_KEYBOARD, AddressOf HookProc, 0, i)
End Sub
'Hook程序
Public Function HookProc(ByVal code As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    '如果code参数<0,则一定要返回CallNextHookEx函数的返回值
    If code < 0 Then
        HookProc = CallNextHookEx(hHook, code, wParam, lParam)
    Else
       '要拦截处理的代码
       '****************
       '如果要拦截处理消息,则HookProc函数的返回值一定要是非0,不然会陷入死循环
        HookProc = 1
    End If
End Function
Sub EndHK()
    UnhookWindowsHookEx hHook
End Sub

 

       

发表评论