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

时间:2016-02-22 21:19:30

标签: windows winapi visual-c++

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

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

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

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

所以我有两个问题:

  1. 为什么会出现这种行为?
  2. 我如何实现理想的行为? (获取所有密钥的状态,最好使用WinAPI。)
  3. P.S。环境:MSVS 2015 Enterprise,Windows 10 Pro。

    #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;
    }
    

2 个答案:

答案 0 :(得分:0)

您应该使用GetKeyboardState来获取所有虚拟密钥的当前状态。

答案 1 :(得分:0)

https://en.wikipedia.org/wiki/Rollover_(key)#Key_jamming_and_ghosting 大多数键盘不能同时按下3个以上的键