挂钩
挂钩是系统消息处理机制中的一点,应用程序可以在挂钩上安装子程序以监视系统中的消息流(消息通信),并且在消息抵达目标窗口过程window procedure之前处理某些类型的消息。(Notes:相当于消息响应函数的前处理 但早于消息抵达响应函数之前)
1、挂钩概述
挂钩是一个应用程序可以截获诸如消息、鼠标动作和键盘输入等事件的机制。拦截特定类型事件的函数称为挂钩过程。挂钩过程可以对接收到的每个事件进行处理,然后修改或丢弃该事件。
下面是一些使用挂钩的例子:
I、出于Debug调试目的监视消息(监视消息以进行调试);
II、提供对宏地记录和回放的支持;
III、为帮助键(F1)提供支持;
IV、模仿鼠标和键盘输入;(猜测可以是这么一种形式:不必为了功能相同的菜单命令与快捷键命令消息分别写消息映射结构体,因为二者的响应函数是相同的。那么此时可以设置挂钩拦截该快捷键命令消息并改写成功能相同的菜单命令消息)
V、实现一个计算机辅助训练程序(Implement a computer-based training (CBT)application);
Notes:由于挂钩增加了系统必须为每个消息执行的处理量,因而会减慢系统。我们应该只在必要的时候安装挂钩程序,并且尽可能快地移除。
2、挂钩链
系统支持许多不同类型的挂钩,每种类型的挂钩都可以访问其消息处理机制的不同方面。例如,应用程序可以适用WH_MOUSE挂钩监视鼠标消息的消息通信。
系统为每种类型的挂钩维护一个独立的挂钩链。一个挂钩链是指向特殊的、应用程序定义的称为挂钩过程(hook procedures)的回调函数的指针的列表(函数指针数组?)。当产生一个与某特定类型的挂钩相关的消息后,系统一个接一个地传递该消息给挂钩链中引用的每个挂钩过程(hook precedure) 。一个挂钩过程能采取的操作取决于关联的挂钩的类型。某些类型的挂钩的挂钩过程只能监视消息;其他类型挂钩的挂钩过程可以修改消息或停止消息在挂钩链中的前进,阻止其抵达下一个挂钩过程或目标窗口(目标窗口的消息映射的响应函数)。
3、挂钩过程
为了利用特定类型的挂钩,开发人员提供了挂钩过程,并使用SegWindowsHookEx()函数将其安装到与挂钩关联的链中。挂钩过程必须具有以下语法:
LRESULT CALLBACK HookProc(
int nCode,
WPARAM wParam,
LPARAM lParam
)
{
// process event
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
其中的"HookProc"是应用程序定义的名称的占位符。
nCode参数是一个挂钩码,挂钩过程用来确定要执行的操作。挂钩码的值取决于挂钩的类型,每个类型的挂钩都有自己特征的一组挂钩码。wParam和lParam参数的值取决于挂钩码,但它们通常包含关于被发送或发布的消息的信息。
SetWindowsHookEx()函数总是在挂钩链的开头安装一个挂钩过程。当由某特殊类型的挂钩所监视的事件发生后,系统调用该挂钩关联的挂钩链开头的(挂钩)过程。挂钩链的每个挂钩过程决定是否传递事件给下个(挂钩)过程。一个挂钩过程通过调用CallNextHookEx()函数传递事件到下一个(挂钩)过程。
一个全局挂钩监视(监视全局所有线程的消息队列?消息队列以线程为单位)与调用线程(即挂钩过程所在的线程)在同一桌面的所有线程的消息(你们这些线程发出的这个消息都到全局挂钩的挂钩过程所在的线程被处理)。特定于线程的挂钩(监视特定线程的消息队列)只能监视单个线程的消息。一个全局的挂钩过程可以被与调用线程(即挂钩过程所在的线程)在同一桌面的任何应用程序中的上下文(context of any application)所调用【可以在与调用线程在同一桌面的任何应用程序的上下文中调用全局挂钩过程】,因此挂钩过程必须在一个独立的DLL模块。特定于线程的挂钩过程仅在关联线程(挂钩过程所在线程)的上下文中被调用。