Почему при чтении клавиш со стрелками из консоли у меня появляется двойное значение «Несколько раз»? - PullRequest
0 голосов
/ 23 января 2020

Я пытаюсь получить ввод с клавиш со стрелками с консоли, но проблема в том, что когда я нажимаю клавишу один раз, она выдает дважды в al oop. Я попытался очистить переменную 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;
      }
   }
}

Ответы [ 2 ]

2 голосов
/ 23 января 2020

Потому что вы получаете уведомления как при нажатии клавиш, так и при нажатии клавиш. Кроме того, если вы удерживаете клавишу, вы получите несколько уведомлений о нажатии клавиш.

Простое решение состоит в том, чтобы просто отслеживать уведомления о нажатии клавиш.

Кроме того, не забудьте проверить возвращаемое значение из 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)

Если вы хотите, чтобы действие происходило при нажатии клавиши, вам может потребоваться добавить дополнительный код для запоминания состояния клавиши, если вы не хотите, чтобы повторения происходили.

0 голосов
/ 30 марта 2020

Это сработало для меня

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, если хотите.

...