当我从控制台读取箭头键时,为什么我有两次多次?
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 文件。
我正在尝试从控制台获取箭头键输入,但问题是当我按下该键时它会循环输出两次。我试图清除 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 文件。