[英]Numpad key events result in stuck keys from GetKeyboardState
I've got a C++ (MFC) app that needs to check the keystate on a timer. 我有一个C ++(MFC)应用程序,需要检查计时器上的键状态。 If the user is holding down a key, we delay processing of some code.
如果用户按住某个键,我们将延迟某些代码的处理。
Here's the check for the keydown
: 这是
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: 但是,有一些关键的组合卡住了:
GetKeyboardState
will now report that VK_UP
is pressed. 现在,
GetKeyboardState
将报告已按下VK_UP
。
The events that happen are (corresponding to the actions above). 发生的事件是(对应于上述操作)。
<None>
WM_KEYDOWN
, VK_SHIFT
WM_KEYDOWN
, VK_SHIFT
WM_KEYUP
, VK_SHIFT
WM_KEYUP
, VK_SHIFT
WM_KEYDOWN
, VK_UP
WM_KEYDOWN
, VK_UP
WM_KEYDOWN
, VK_SHIFT
WM_KEYDOWN
, VK_SHIFT
WM_KEYUP
, VK_SHIFT
WM_KEYUP
, VK_SHIFT
WM_KEYUP
, VK_NUMPAD8
WM_KEYUP
, VK_NUMPAD8
So, Windows doesn't recognize that the Up key came up, and now GetKeyboardState
is broken. 因此,Windows无法识别出Up键,现在
GetKeyboardState
已损坏。
Is there any good way to check the real state of the key? 有什么好的方法可以检查密钥的真实状态?
GetAsyncKeyState
and GetKeyState
both report that the key is down as well. GetAsyncKeyState
和GetKeyState
都报告密钥也已按下。
Solved it. 解决了。
I hooked into the keyboard events in InitInstance and am tracking the ups and downs by scan code (a map with the scan code as key and the virtual keys as the value). 我迷上了InitInstance中的键盘事件,并通过扫描代码(以扫描代码为键,虚拟键为值的映射)跟踪起伏。
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 defer checking 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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.