提示: 如果要设置系统级钩子, 钩子函数必须在 DLL 中.
WINUSERAPI
HHOOK {返回钩子的句柄; 0 表示失败}
WINAPI
SetWindowsHookEx(
int idHook, {钩子类型}
HOOKPROC lpfn, {函数指针}
HINSTANCE hmod, {包含钩子函数的模块(EXE、DLL)句柄; 一般是 HInstance; 如果是当前线程这里可以是 0}
DWORD dwThreadId); {关联的线程; 可用 GetCurrentThreadId 获取当前线程; 0 表示是系统级钩子}
) //钩子类型 idHook 选项: WH_MSGFILTER = -1; {线程级; 截获用户与控件交互的消息} WH_JOURNALRECORD = 0; {系统级; 记录所有消息队列从消息队列送出的输入消息, 在消息从队列中清除时发生; 可用于宏记录} WH_JOURNALPLAYBACK = 1; {系统级; 回放由 WH_JOURNALRECORD 记录的消息, 也就是将这些消息重新送入消息队列} WH_KEYBOARD = 2; {系统级或线程级; 截获键盘消息} WH_GETMESSAGE = 3; {系统级或线程级; 截获从消息队列送出的消息} WH_CALLWNDPROC = 4; {系统级或线程级; 截获发送到目标窗口的消息, 在 SendMessage 调用时发生} WH_CBT = 5; {系统级或线程级; 截获系统基本消息, 譬如: 窗口的创建、激活、关闭、最大最小化、移动等等} WH_SYSMSGFILTER = 6; {系统级; 截获系统范围内用户与控件交互的消息} WH_MOUSE = 7; {系统级或线程级; 截获鼠标消息} WH_HARDWARE = 8; {系统级或线程级; 截获非标准硬件(非鼠标、键盘)的消息} WH_DEBUG = 9; {系统级或线程级; 在其他钩子调用前调用, 用于调试钩子} WH_SHELL = 10; {系统级或线程级; 截获发向外壳应用程序的消息} WH_FOREGROUNDIDLE = 11; {系统级或线程级; 在程序前台线程空闲时调用} WH_CALLWNDPROCRET = 12; {系统级或线程级; 截获目标窗口处理完毕的消息, 在 SendMessage 调用后发生}
WH_KEYBOARD_LL = 13; //(_WIN32_WINNT >= 0x0400)
WH_MOUSE_LL = 14; //(_WIN32_WINNT >= 0x0400)
关于低级钩子与非低级钩子的区别:以WH_KEYBOARD_LL与WH_KEYBOARD 为例
钩的位置不同,WH_KEYBOARD_LL 要比WH_KEYBOARD 先触发,WH_KEYBOARD_LL 是由系统调用你的回调函数,而WH_KEYBOARD则是你钩的进程来调用你的回调函数。这就意味着,WH_KEYBOARD要插入进程,如果是全局钩子,就会插入每一个进程,WH_KEYBOARD_LL 不需要插入进程(所以据说根本不需要放在dll里面,放在exe里面也能运行,未经测试!)
一个全局钩子的例子
http://www.xiaozhou.net/ReadNews.asp?NewsID=909
要做成全局钩子,最主要的就是要把钩子回调函数放在DLL里面,这样,在运用SetWindowsHookEx的时候,
才能把你的DLL插入到系统每一个进程当中,这样才能截获全局范围内的消息。而我们需要做的,就是建立三个变量,
分别统计鼠标左键、右键、和键盘按键的总和。必须注意的是由于这三个变量是必须共享的,所以需要建立一个数据段,
把数据段的属性设置为可读、可写、可共享的属性。并在数据段中定义这三个变量,这样就可以达到目的了。
把数据段设置成可读、可写、共享的方法:
1、在DLL的def文件中加入SECTIONS MyData READ WRITE SHARED
2、在编译器选项里面加入 /SECTION:MyData,rws