В последнее время я столкнулся с этой проблемой. Я не могу найти никаких хороших решений, но в итоге я использовал флаг и GetAsyncKeyState
до SetWindowHookEx
.
BOOL wasDown;
LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) {
if (nCode == HC_ACTION) {
LPKBDLLHOOKSTRUCT key = (LPKBDLLHOOKSTRUCT) lParam;
if (key->vkCode == VK_SOMETHING) {
switch (wParam) {
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
if (!wasDown) {
// Processing on first key down
wasDown = true;
}
break;
case WM_KEYUP:
case WM_SYSKEYUP:
// Processing on key up
wasDown = FALSE;
break;
}
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
wasDown = GetAsyncKeyState(VK_SOMETHING) < 0;
hHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, hInstance, 0);
Конечно, этот код делает это только для одного ключа. Вы можете использовать массив флагов для выполнения нескольких клавиш. В зависимости от вашего приложения вы также можете безоговорочно установить флаг на false
, если вы хотите, чтобы первое нажатие после того, как ваш крючок установлен.
Одна из многих проблем с клавиатурными крючками, состояние клавиатуры - свойство для каждого процесса. Итак, все, что вы получаете, полностью зависит от того, какой процесс имеет собственное окно переднего плана и есть ли он * раньше. –
Я знаю, но в данном случае мне все равно. Я ожидаю, что пользователь сосредоточится только на моем процессе, но я знаю о риске, спасибо! –
@Hans Состояние клавиатуры контролируется на поток (или группу потоков, если несколько потоков связаны друг с другом в результате вызова 'AttachThreadInput'). Замена всех вхождений * process * с помощью * потока или группы потоков * исправляет ваш комментарий. – IInspectable