当我从控制台读取箭头键时,为什么我有两次多次?

Why I am having double Multiple times When I read Arrow Keys from Console?

我正在尝试从控制台获取箭头键输入,但问题是当我按下该键时它会循环输出两次。我试图清除 INPUT_RECORD 变量,但常用方法似乎不起作用。

#include <iostream>
#include <windows.h>
#include <WinUser.h>

using namespace std;

int main()
{
    HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE);
    DWORD NumInputs = 0;
    DWORD InputsRead = 0;
    INPUT_RECORD irInput;

    irInput.Event.KeyEvent.wVirtualKeyCode = 0;

    GetConsoleMode(hInput, &NumInputs);
    SetConsoleMode(hInput, 0);
    GetNumberOfConsoleInputEvents(hInput, &NumInputs);

    while (true)
    {
     ReadConsoleInput(hInput, &irInput, 1, &InputsRead);

     switch (irInput.Event.KeyEvent.wVirtualKeyCode)
     {    
      case VK_DOWN:
           cout << "DOWN";
           break;

       case VK_LEFT:
            cout << "LEFT";
            break;

       case VK_RETURN:
            cout << "ENTER";
            break;

       case VK_RIGHT:
            cout << "RIGHT";
            break;

       case VK_UP:
            cout << "UP";
            break;
      }
   }
}

因为您会同时收到按下键和按下键的通知。此外,如果您按住该键,您将收到多个按键按下通知。

简单的解决方法是只跟踪按键通知。

顺便说一句,不要忘记检查 ReadConsoleInput 中的 return 值。

而不是这个:

while (true)
{
    ReadConsoleInput(hInput, &irInput, 1, &InputsRead);

    if (irInput.Event.KeyEvent.bKeyDown)
    {
        continue;
    }

    switch (irInput.Event.KeyEvent.wVirtualKeyCode)

这个:

while (true)
{
    BOOL result = ReadConsoleInput(hInput, &irInput, 1, &InputsRead);

    if (!result || irInput.Event.KeyEvent.bKeyDown)
    {
        continue;
    }

    switch (irInput.Event.KeyEvent.wVirtualKeyCode)

如果您希望在按键按下时发生动作,您可能需要添加额外的代码来记住按键状态,除非您希望重复发生。

这对我有用

int KeysInput()
{
    HANDLE _GetStdHandle();
    WORD ReadVkCode(HANDLE InputHandle);

    try {
        HANDLE InputHandle = _GetStdHandle();
        WORD InputRecord = ReadVkCode(InputHandle);

        switch (InputRecord)
        {
         case VK_DOWN:
           cout << "DOWN";
           break;

       case VK_LEFT:
            cout << "LEFT";
            break;

       case VK_RETURN:
            cout << "ENTER";
            break;

       case VK_RIGHT:
            cout << "RIGHT";
            break;

       case VK_UP:
            cout << "UP";
            break;
        }
    }
    catch (const std::exception & ex) {
        std::cerr << ex.what();
        return 1;
    }
}

HANDLE _GetStdHandle()
{ 
   HANDLE InputHandle;

    if ((InputHandle = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE)
        throw std::runtime_error("Failed to get standard input handle.");

    return InputHandle;
}

WORD ReadVkCode(HANDLE InputHandle)
{
    INPUT_RECORD InputRecord;
    DWORD InputsRead;

    while (ReadConsoleInput(InputHandle, &InputRecord, 1, &InputsRead) && InputsRead == 1)
        if (InputRecord.EventType == KEY_EVENT && InputRecord.Event.KeyEvent.bKeyDown)
            return InputRecord.Event.KeyEvent.wVirtualKeyCode;

    throw std::runtime_error("Failed to read input.");
}

如果需要,您可以将其用作 .h 文件。