按下多个键时,GetAsyncKeyState 不起作用

GetAsyncKeyState do not work when multiple keys are pressed

提问人:Pavel Dubsky 提问时间:2/23/2016 更新时间:8/30/2016 访问量:2139

问:

我在使用函数获取键盘状态时遇到问题(我尝试使用函数,但结果相同)。GetAsyncKeyStateGetKeyboardState

我需要实现以下功能:在每个帧应用程序上应处理所有可用的 Windows 消息、执行帧更新例程和帧渲染例程。对于更新部分,我需要在更新时获取键盘状态(这就是我使用而不是 )。GetAsyncKeyStateGetKeyState

我编写了一个示例代码来演示我得到的行为。它将按下的键列表设置为窗口的标题。为简单起见,它只处理 alpha 键。

用例示例:按 A 键但不要松开,然后按 B,然后按 C。现在标题中应该是“A、B、C”。如果您按 D 键,它应该显示为“A、B、C、D”,但事实并非如此。您可以尝试不同的组合键。有时它会显示按下的 5、6 甚至更多键。

所以我有两个问题:

  1. 为什么会出现这种行为?
  2. 我怎样才能实现期望的行为?(获取所有密钥的状态,最好使用 WinAPI。

PS 环境:MSVS 2015 企业版、Windows 10 专业版。

#include <Windows.h>
#include <string>

using namespace std;

void Render(HWND window, wstring keyboardState)
{
    SetWindowText(window, keyboardState.c_str());
}

void UpdateKeyState(int key, wstring& keyboardState)
{
    if ((GetAsyncKeyState(key) & 0x8000) != 0)
    {
        keyboardState.append(1, key);
        keyboardState.append(L", ");
    }
}

void Update(wstring& keyboardState)
{
    keyboardState.clear();

    UpdateKeyState('A', keyboardState);
    UpdateKeyState('B', keyboardState);
    UpdateKeyState('C', keyboardState);
    UpdateKeyState('D', keyboardState);
    UpdateKeyState('E', keyboardState);
    UpdateKeyState('F', keyboardState);
    UpdateKeyState('G', keyboardState);
    UpdateKeyState('H', keyboardState);
    UpdateKeyState('I', keyboardState);
    UpdateKeyState('J', keyboardState);
    UpdateKeyState('K', keyboardState);
    UpdateKeyState('L', keyboardState);
    UpdateKeyState('M', keyboardState);
    UpdateKeyState('N', keyboardState);
    UpdateKeyState('O', keyboardState);
    UpdateKeyState('P', keyboardState);
    UpdateKeyState('Q', keyboardState);
    UpdateKeyState('R', keyboardState);
    UpdateKeyState('S', keyboardState);
    UpdateKeyState('T', keyboardState);
    UpdateKeyState('U', keyboardState);
    UpdateKeyState('V', keyboardState);
    UpdateKeyState('W', keyboardState);
    UpdateKeyState('X', keyboardState);
    UpdateKeyState('Y', keyboardState);
    UpdateKeyState('Z', keyboardState);
}

LRESULT CALLBACK WindowProcedure(HWND window, UINT message, WPARAM wParam, LPARAM lParam)
{
    LRESULT result = 0l;

    switch (message)
    {
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            result = DefWindowProc(window, message, wParam, lParam);
            break;
    }

    return result;
}

int WINAPI wWinMain(HINSTANCE instance, HINSTANCE, LPWSTR commandLine, int showCommand)
{
    WCHAR className[] = L"KeyboardStateApplication";

    WNDCLASSEX windowClass = { };
    windowClass.cbSize = sizeof(windowClass);
    windowClass.hInstance = instance;
    windowClass.lpfnWndProc = WindowProcedure;
    windowClass.lpszClassName = className;

    int exitCode = 0;

    if (RegisterClassEx(&windowClass))
    {
        HWND window = CreateWindowEx(0ul, className, nullptr, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, nullptr, nullptr, instance, nullptr);

        ShowWindow(window, showCommand);
        UpdateWindow(window);

        MSG message = { };
        bool exit = false;

        wstring keyboardState;

        while (true)
        {
            while (PeekMessage(&message, nullptr, 0u, 0u, PM_NOREMOVE))
            {
                if (GetMessage(&message, nullptr, 0u, 0u))
                {
                    DispatchMessage(&message);
                }
                else
                {
                    exit = true;
                    break;
                }
            }

            if (exit)
            {
                break;
            }
            else
            {
                Update(keyboardState);
                Render(window, keyboardState);
            }
        }

        exitCode = message.wParam;
    }

    return exitCode;
}
Windows WinAPI 视觉 C++

评论

0赞 David Heffernan 2/23/2016
可能是实际键盘的限制,通常只能同时记录少量按键
0赞 Pavel Dubsky 2/23/2016
我也想到了这一点,但为什么它如此不确定?有时我会得到 3 个键的正确状态,有时会得到 8 个甚至更多的正确状态。
3赞 dxiv 2/23/2016
例如,请参阅键盘重影解释
0赞 Hans Passant 5/18/2016
en.wikipedia.org/wiki/Rollover_%28key%29

答:

0赞 Ton Plooij 5/16/2016 #1

应使用 GetKeyboardState 获取所有虚拟键的当前状态。

评论

0赞 Pavel Dubsky 5/20/2016
正如我在 OP 中提到的,我已经尝试使用它。问题出在硬件上。
0赞 Devaniti 8/30/2016 #2

https://en.wikipedia.org/wiki/Rollover_(key)#Key_jamming_and_ghosting大多数键盘无法同时读取超过 3 个键