【问题标题】:Why do I receive each keyboard event twice when using ReadConsoleInput?为什么在使用 ReadConsoleInput 时我会收到两次键盘事件?
【发布时间】:2014-03-27 00:09:28
【问题描述】:

好的,开始这个话题我想说我对编码比较陌生。话虽如此,如果问题太模糊而无法理解,我深表歉意。

以下代码来自我为 Win32 制作的第一个真正的 c++ 程序。函数playerMove 将玩家图标移动到屏幕上的新位置,同时用 X 替换旧位置。

我不知道为什么,但每当我按下任何键以引起移动时,它都会执行两次操作。我不确定我读取输入缓冲区的方式是什么,但我想知道是否有一个我刚刚错过的简单解释。我在每个案例的末尾都添加了FlushConsoleInputBuffer,以防出现问题,但这似乎并没有解决问题。

void playerMove()
{

    HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE);
    DWORD NumInputs = 0;
    DWORD InputsRead = 0;
    bool running = true;

    INPUT_RECORD irInput;

    GetNumberOfConsoleInputEvents(hInput, &NumInputs);

    while(running)
    {
        ReadConsoleInput(hInput, &irInput, 1, &InputsRead);
        //std::cout << irInput.Event.KeyEvent.wVirtualKeyCode << std::endl;

            HANDLE hStdout; 
            CONSOLE_SCREEN_BUFFER_INFO csbiInfo; 
            COORD coordDest; 

        switch(irInput.Event.KeyEvent.wVirtualKeyCode)
        {
            case M_KEY:
                FlushConsoleInputBuffer(hInput);
                displayMenu();                
                //Opens the menu
            break;

            case VK_LEFT:

            hStdout = GetStdHandle(STD_OUTPUT_HANDLE); 
            coordDest.X=xcoord;
            coordDest.Y=ycoord;
            SetConsoleCursorPosition(hStdout, coordDest);
            cout<<'X';
            coordDest.X=(xcoord-1);
            SetConsoleCursorPosition(hStdout, coordDest);
            SetColor(11);
            cout<<'@';
            SetColor(7);
            xcoord--;
            FlushConsoleInputBuffer(hInput);
            // move it left
            break;

        case VK_UP:

            hStdout = GetStdHandle(STD_OUTPUT_HANDLE); 
            coordDest.X=xcoord;
            coordDest.Y=ycoord;
            SetConsoleCursorPosition(hStdout, coordDest);
            cout<<'X';
            coordDest.Y=(ycoord-1);
            SetConsoleCursorPosition(hStdout, coordDest);
            SetColor(11);
            cout<<'@';
            SetColor(7);
            ycoord--;
            FlushConsoleInputBuffer(hInput);
            // move it up
            break;
        case VK_RIGHT:

            hStdout = GetStdHandle(STD_OUTPUT_HANDLE); 
            coordDest.X=xcoord;
            coordDest.Y=ycoord;
            SetConsoleCursorPosition(hStdout, coordDest);
            cout<<'X';
            coordDest.X=(xcoord+1);
            SetConsoleCursorPosition(hStdout, coordDest);
            SetColor(11);
            cout<<'@';
            SetColor(7);
            xcoord++;
            FlushConsoleInputBuffer(hInput);
            // move it right
            break;

        case VK_DOWN:

            hStdout = GetStdHandle(STD_OUTPUT_HANDLE); 
            coordDest.X=xcoord;
            coordDest.Y=ycoord;
            SetConsoleCursorPosition(hStdout, coordDest);
            cout<<'X';
            coordDest.Y=(ycoord+1);
            SetConsoleCursorPosition(hStdout, coordDest);
            SetColor(11);
            cout<<'@';
            SetColor(7);
            ycoord++;
            FlushConsoleInputBuffer(hInput);
            // move it down
            break;

        } 

    }
}

【问题讨论】:

  • ...来自我的第一个真正的 c++ 程序... winapi 本质上是不是 c++!!使用 c++ 标准std::cinstd::cout 与控制台 IO 交互呢??
  • 确实有两个按键通知。跌的时候一个,涨的时候一个。您忘记查看KEY_EVENT_RECORD.bKeyDown member。您还忘记检查 INPUT_RECORD.EventType,您从这个 winapi 函数获得的不仅仅是键盘输入。
  • @πάνταῥεῖ 这只是我代码的一部分,我在其中使用更多的 winapi 以更易于编写和理解的方式操作控制台。如前所述,我是一名新程序员,所以当我启动这个程序时“使用命名空间 std;”是我开始的,我一定会在完成之前修复它。
  • @HansPassant 谢谢汉斯的实际建议。你为我节省了数小时的搜索时间。现在已经很晚了,但我明天会尝试实施,我毫不怀疑它会起作用。
  • @πάνταῥεῖ,Windows API 并没有排除使用 C++。至于使用 C++ 流 I/O 与控制台交互,我认为这个问题中的代码说明了不这样做的一个很好的理由:C++ 标准库没有提供读取箭头键或在屏幕上移动光标的设施。

标签: c++ winapi windows-console


【解决方案1】:

通过在 switch 语句之前添加一个 if 语句来检查一个键是否被按下 (bKeyDown),它只会通过首先检查一个键是否按下来捕获该键被按下。所以这个问题可以认为是已回答。

【讨论】:

    猜你喜欢
    • 2012-04-09
    • 1970-01-01
    • 2019-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多