我想在C ++中检测keypress,我需要使用Windows系统调用。所以,我做了一些研究,这就是我使用Hooks和Message:
#include <Windows.h>
#include <iostream>
#include <sstream>
#include <fstream>
#include <ctime>
using namespace std;
LRESULT CALLBACK LowLevelKeyboardProc(int code, WPARAM wParam, LPARAM lParam) {
if (code == HC_ACTION) {
switch (wParam) {
case WM_KEYDOWN:
PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT)lParam;
char c = char(MapVirtualKey(p->vkCode, MAPVK_VK_TO_CHAR));
cout << c << endl;
}
}
return CallNextHookEx(NULL, code, wParam, lParam);
}
int main() {
HHOOK HKeyboard = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, 0, 0);
MSG msg;
BOOL bRet;
while ((bRet = GetMessage(&msg, NULL, 0, 0)) > 0) {
cout << "bRet = " << bRet << endl; // I want to do something here, but the program doesn't seem to go in here
TranslateMessage(&msg);
DispatchMessage(&msg);
}
UnhookWindowsHookEx(HKeyboard);
return 0;
}
我的问题是为什么我的程序没有进入循环(而是停留在GetMessage函数上)?我需要它设置条件在几秒后终止,那么我应该把条件放在哪里?我知道GetMessage函数读取了Message,但是当我按下键盘上的键时它仍然没有进入并且回调函数工作正常。
答案 0 :(得分:2)
事件将发布到活动窗口。控制台窗口由控制台子系统csrss.exe拥有,它接收事件,然后将它们转换为字符并将它们放在控制台对象中,该对象是应用程序的stdin
。
如果要以Win32 GUI方式处理事件,则应使用Win32窗口(例如RegisterClass
和CreateWindow
),而不是控制台窗口。
如果您只想让回调在一段时间内有效,您可以使用可提醒的等待时间,例如SleepEx
或MsgWaitForMultipleObjects
,等待超时。
答案 1 :(得分:0)
这并不奇怪,你的线程队列中确实没有任何消息,你没有窗口,所以也没有窗口队列。
如果你想玩钩子返回的值,把代码放在钩子回调函数中。
我应该警告你,由于控制台窗口位于另一个进程中,因此这些钩子不能在控制台应用程序中工作。另外,如果你查看SetWindowsHookEx
的MSDN页面,你会发现WH_KEYBOARD_LL
只是一个全局钩子,即你必须将你的钩子处理程序放在DLL库中并注入钩子在其他应用程序中。然后你必须自己处理32/64位问题。
最后一点,当您在处理程序中说cout << c;
时,会在流程的输出文件句柄中打印,而不是您自己的句柄。