Numpad Keyboard Events Jam Keys from GetKeyboardState

I have a C ++ application (MFC) for which I need to check the keystat on the timer. If the user holds the key, we delay the processing of some code.

Here's the check for keydown :

 if (!GetKeyboardState(keyState)) { s_executeDeferredResult = e_executeDeferredButtonCheckFailed; return; } s_executeDeferredStuckKeys.clear(); for (int index=0; index<arrsize(keyState); ++index) { if (keyState[index] & 0x80) { s_executeDeferredStuckKeys.insert(index); } } if (!s_executeDeferredStuckKeys.empty()) { s_executeDeferredResult = e_executeDeferredButtonsActive; return; } 

But there are some key combos that get stuck:

  • Enable NUMLOCK
  • Press SHIFT
  • Click NumPad8
  • Release SHIFT
  • NumPad8 Release
    (this is one example, there are others, including doozy with CTRL - ALT - DEL )

GetKeyboardState will now report that VK_UP pressed.

Events that occur (correspond to the actions above).

  • <None>
  • WM_KEYDOWN , VK_SHIFT
  • WM_KEYUP , VK_SHIFT
    WM_KEYDOWN , VK_UP
    WM_KEYDOWN , VK_SHIFT
  • WM_KEYUP , VK_SHIFT
  • WM_KEYUP , VK_NUMPAD8

So, Windows does not recognize that the Up key has risen, and now GetKeyboardState broken.

Is there a good way to check the real state of a key? GetAsyncKeyState and GetKeyState report that the key is also turned off.

+4
source share
1 answer

I decided.

I connected to keyboard events in InitInstance and track ups and downs with a scan code (card with scan code as key and virtual keys as value).

 m_keyboardHook = SetWindowsHookEx(WH_KEYBOARD, &KeyboardHook, NULL, GetCurrentThreadId()); 

 static LRESULT CALLBACK KeyboardHook( __in int nCode, __in WPARAM wParam, __in LPARAM lParam ) { // According to the docs, we're not allowed to do any "further processing" if nCode is < 0. // According to the docs, we should process messages if we get code HC_ACTION. // http://msdn.microsoft.com/en-us/library/windows/desktop/ms644984(v=vs.85).aspx // It doesn't specify what to do if another code comes in, so we will just ignore any other codes. if (nCode == HC_ACTION) { uint8 scanCode = (uint8)((lParam & 0x00FF0000) >> 16); uint8 virtKey = (uint8)wParam; if (lParam & 0x80000000) // key up KeyState::SetKeyUp(scanCode); else KeyState::SetKeyDown(scanCode, virtKey); } // We must call the next hook in the chain, according to http://msdn.microsoft.com/en-us/library/windows/desktop/ms644975%28v=vs.85%29.aspx // First param is ignored, according to http://msdn.microsoft.com/en-us/library/windows/desktop/ms644974%28v=vs.85%29.aspx ) return CallNextHookEx(0, nCode, wParam, lParam); } 

So my check for deferral becomes:

 // Similarly, don't process deferred events if there are keys or mouse buttons which are currently down. s_executeDeferredStuckKeys.clear(); if (KeyState::AnyKeysDown(s_excludeKeys, arrsize(s_excludeKeys))) { s_executeDeferredResult = e_executeDeferredButtonsActive; KeyState::GetDownKeys(s_executeDeferredStuckKeys); return; } 
+2
source

Source: https://habr.com/ru/post/1499506/


All Articles