此动态链接库还提供有输出函数StopHook(),调用
程序通过对此函数的调用完成对先前加载钩子的卸载。在此输出函数内则是通过UnhookWindowsHookEx()函数来卸载指定钩子的:
BOOL CMouseHook::StopHook() { BOOL result = FALSE; if (glhHook){ result = UnhookWindowsHookEx((HHOOK)glhHook); // 卸载钩子 if (result) glhDisplayWnd = glhPrevTarWnd = glhHook = NULL; } return result; } |
通过编译、链接可以得到有关鼠标全局钩子的动态链接库,在经过调用程序对其的调用后,可以实现对在当前系统所有线程中的鼠标消息的拦截处理。在钩子动态链接库加载到进程后,只需调用输出函数StartHook()安装好全局钩子即可对鼠标消息进行拦截过滤,在调用
程序退出前调用输出函数StopHook()卸载钩子。
使用键盘钩子 键盘钩子同鼠标钩子一样,也是一类较常用的钩子。而且总的来说键盘钩子的使用与鼠标钩子的使用也是比较类似的,下面通过一个
程序实例来对键盘钩子的使用进行介绍,在此例程中通过设置键盘全局钩子来记录当前系统输入的字符,并将拦截到的字符按日期保存到文件。
由于本例程也使用的系统全局钩子,因此由调用程序和动态链接库程序两部分组成。动态链接库
程序提供了两个输出函数InstallLaunchEv()和UnInstall(),分别用于键盘钩子的安装与卸载:
DllExport void WINAPI InstallLaunchEv() { glhHook = (HHOOK)SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC)LauncherHook, theApp.m_hInstance, 0); // 安装键盘钩子 } DllExport void WINAPI UnInstall() { if (glhHook) { BOOL result = UnhookWindowsHookEx((HHOOK)glhHook); // 卸载钩子 if (result) glhHook = NULL; } } |
在钩子安装函数中,通过SetWindowsHookEx()设置了键盘钩子函数LauncherHook()。在键盘事件发生后此钩子函数将被调用,通过SaveLog()函数将捕获到的字符保存到文件:
LRESULT CALLBACK LauncherHook(int nCode, WPARAM wParam, LPARAM lParam) { // 将键盘事件传递给下一钩子函数 LRESULT Result = CallNextHookEx(glhHook, nCode, wParam, lParam); if (nCode == HC_ACTION) // 处理键盘动作 { if (lParam & 0x80000000) // 保存键盘动作到文件 { char c; c[0] = wParam; SaveLog(c); if (c[0] == 13) { c[0] = 10; SaveLog(c); } } } return Result; } |
至于调用程序则非常简单,只是在程序开始运行后和在
程序退出前分别调用动态链接库提供的钩子设置函数和钩子卸载函数即可。
钩子的种类有很多,从前面给出的鼠标钩子和键盘钩子也可以看出其编写过程是非常类似的。通常情况下作为钩子载体的动态链接库要提供有两个必要的输出函数——钩子安装函数和钩子卸载函数。在钩子安装函数中通过SetWindowsHookEx()为不同类型的钩子设置相应的钩子函数,实质性的工作也主要是在钩子函数中完成的,具体情况应视钩子的类型和要完成的功能而定。在钩子卸载函数中则主要是对UnhookWindowsHookEx()的调用,并辅以必要的保护性代码。