Я хочу обнаружить нажатие клавиш в C ++, и мне нужно использовать системный вызов 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 читает сообщение, но когда я нажимаю клавиши на клавиатуре, она все равно не включается, и функция обратного вызова работает просто отлично.
События публикуются в активном окне. Окна консоли принадлежат консольной подсистеме csrss.exe, и она получает события, затем преобразует их в символы и помещает их в объект консоли, который является приложением вашего приложения. stdin
,
Если вы хотите обрабатывать события способом Win32 GUI, вы должны использовать окно Win32 (например, RegisterClass
а также CreateWindow
), а не консольное окно.
Если вы просто хотите, чтобы обратные вызовы работали в течение определенного периода времени, вы можете использовать предупреждающее ожидание, такое как SleepEx
или же MsgWaitForMultipleObjects
, которые принимают тайм-аут.
Это не удивительно, в вашей очереди потоков нет никаких сообщений, и у вас нет окна, поэтому нет и очереди окна.
Если вы хотите поиграть со значениями, возвращенными из ловушки, поместите код в функцию обратного вызова ловушки.
Я должен предупредить вас, что подобные хуки не будут работать в консольных приложениях, так как окно консоли находится в другом процессе. Кроме того, если вы посмотрите на страницу MSDN для SetWindowsHookEx
, вы увидите, что WH_KEYBOARD_LL
это только глобальный хук, т.е. вы должны поместить свой обработчик хука в библиотеку DLL и внедрить хук в другие приложения. Затем вы должны решить 32/64 битную проблему самостоятельно.
И как последнее замечание, когда вы говорите, cout << c;
в вашем обработчике, это будет печать в дескрипторе выходного файла процесса, не твой собственный.