【问题标题】:Why I am having double Multiple times When I read Arrow Keys from Console?当我从控制台读取箭头键时,为什么我有两次多次?
【发布时间】:2020-05-10 00:32:38
【问题描述】:

我正在尝试从控制台获取箭头键输入,但问题是当我按下该键时,它会在循环中提供两次输出。我试图清除 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;
      }
   }
}

【问题讨论】:

  • 您好,请问有什么解决方法吗?请随时为有相同问题的人标记它。
  • 解决我问题的代码如下...

标签: windows winapi visual-c++ user32


【解决方案1】:

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

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

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

而不是这个:

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)

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

【讨论】:

    【解决方案2】:

    这对我有用

    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 文件。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-09
      • 2021-08-31
      • 1970-01-01
      • 2021-11-29
      • 2019-01-30
      • 1970-01-01
      • 2011-10-06
      • 2022-06-16
      相关资源
      最近更新 更多