今天正好帮新人同事解决了个键盘监听的问题,顺手把踩坑过程记下来。本来以为就是个简单的键盘钩子,结果折腾半天才发现KeyboardProc这玩意儿门道挺多。
起手就掉坑里
最开始直接复制了段网上的代码,想着不就是个键盘事件回调嘛啪嗒啪嗒敲完编译,嚯,根本不起作用!气得我直拍大腿。扭头查文档才看见这行小字:Hook必须放在独立线程里跑。新手最容易栽在这步:
- 傻乎乎把SetWindowsHookEx塞进主线程
- 回调函数里乱塞耗时操作
- 连WH_KEYBOARD和WH_KEYBOARD_LL都分不清
低层钩子上线
干脆重头撸代码。先拉个专属线程打地基:
CreateThread → SetWindowsHookEx(WH_KEYBOARD_LL) → MSG循环三板斧架这回学乖了,在回调函数开头就加日志输出,手指刚碰键盘,调试窗口果然噼里啪吐字符码。
正得意突然程序卡死,鼠标指针转起小圈圈。原来同事在回调里写了个网络请求——这不要命嘛赶紧给他画红线:KeyboardProc里超过1毫秒的操作都是在作死,应该立刻把数据丢进队列让其他线程处理。
键鼠组合翻车现场
测试Ctrl+C复制功能时又露馅了。单按Ctrl键疯狂刷事件,松开时却抓不到释放信号。折腾半天才悟出来:系统把修饰键(Ctrl/Alt)和普通键分开处理。解决土办法是弄个全局变量当开关,像这样:
- 检测到Ctrl按下:flag_ctrl = true
- 检测到C键按下:if(flag_ctrl) 执行复制
- 检测到Ctrl松开:flag_ctrl = false
终极安全指南
给新手三条保命符:
- 别在回调里碰任何UI控件(血泪教训)
- 全局钩子要用LoadLibrary加载(否则分分钟崩溃)
- 安装前先CallNextHookEx腾出系统通道
现在看新人调试成功的样子,想起自己当年连钩子链是啥都不懂,硬是把键盘监听写成键盘毁灭者。弄懂KeyboardProc就像学骑自行车,摔个五六次自然就会了——重点是你得知道该护着哪儿别摔太惨。