我想检测C ++中的按键,我需要使用Windows系统调用。 所以,我做了一些研究,这就是我使用钩子和消息:
#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函数读取消息,但是当我按下我的键盘上的键,它仍然不会进入,callback函数工作得很好。
事件被发送到活动窗口。 控制台窗口由控制台子系统csrss.exe所有,它接收事件,然后将它们转换为字符,并将它们放在控制台对象中,这是您的应用程序的stdin
。
如果你想处理事件的Win32 GUI方式,你应该使用Win32窗口(例如RegisterClass
和CreateWindow
),而不是控制台窗口。
如果您只想让回调工作一段时间,则可以使用SleepEx
或MsgWaitForMultipleObjects
等可接受等待时间的警示等待接受超时。
这并不奇怪,线程队列中没有任何消息,并且没有窗口,所以也没有窗口队列。
如果你想玩从钩子返回的值,把代码放在钩子回调函数中。
我应该警告你,像这样的钩子将不能在控制台应用程序中工作,因为控制台窗口驻留在另一个进程中。 此外,如果您查看SetWindowsHookEx
的MSDN页面,您将看到WH_KEYBOARD_LL
只是一个全局钩子,即您必须将钩子处理程序放在DLL库中并在其他应用程序中注入钩子。 那么你必须自己处理32/64位的问题。
作为最后一点,当你说cout << c;
在你的处理程序中,这将打印在进程的输出文件句柄中 ,而不是你自己的。