首页 > 解决方案 > 标准输入中的 C++ Windows 密钥检测

问题描述

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

constexpr auto KEY_FORWARD = 'w';
constexpr auto KEY_BACKWARD = 's';
constexpr auto KEY_LEFT = 'a';
constexpr auto KEY_RIGHT = 'd';
constexpr auto KEY_UP = 't';
constexpr auto KEY_DOWN = 'g'; 


bool updateKey(char keyValue, bool* key_control, KEY_EVENT_RECORD ker){
    if (ker.uChar.AsciiChar == keyValue) {
        *key_control = ker.bKeyDown;
        std::cout << ker.bKeyDown ;
        return TRUE;
    }
    return FALSE;
}

int main() 
{
    using namespace std;

    HANDLE hIn;
    HANDLE hOut;
    bool _continue = TRUE;
    INPUT_RECORD inRec[128];
    DWORD numRead;
    hIn = GetStdHandle(STD_INPUT_HANDLE);
    hOut = GetStdHandle(STD_OUTPUT_HANDLE);
  
    bool left_control,right_control,up_control,down_control,forward_control,backward_control;
    left_control =  FALSE;
    right_control = FALSE;
    up_control = FALSE;
    down_control = FALSE;
    forward_control = FALSE;
    backward_control = FALSE;
    while (_continue) {
        if (!ReadConsoleInput(hIn, inRec, 128, &numRead)) {
            continue;
        }
        for (DWORD i = 0; i < numRead; i++) {
            if (inRec[i].EventType != KEY_EVENT) {
                continue;
            }
            if (updateKey(KEY_UP, &up_control, inRec[i].Event.KeyEvent)) continue;
            if (updateKey(KEY_DOWN, &down_control, inRec[i].Event.KeyEvent)) continue;
            if (updateKey(KEY_LEFT, &left_control, inRec[i].Event.KeyEvent)) continue;
            if (updateKey(KEY_RIGHT, &right_control, inRec[i].Event.KeyEvent)) continue;
            if (updateKey(KEY_FORWARD, &forward_control, inRec[i].Event.KeyEvent)) continue;
            if (updateKey(KEY_BACKWARD, &backward_control, inRec[i].Event.KeyEvent)) continue;

        }
    }

    return 0;
}

上面是一个简单的脚本,它从标准输入中获取输入。

当我运行它并按住'a'键有效地将'a'输入标准输入时,我得到“1010101010101010 ....”,这告诉我Windows API认为我反复按下和释放该键。

ReadConsoleInput的文档说 numRead 应该指向输出的输入记录数。每次我按下一个键时,它都会将 numRead 设置为 2。这两个记录分别对应于按下的单个键,但是,在 KEY_EVENT_RECORD(s) 之一中,bKeyDown 为 1,第二个为 0。 KEY_EVENT_RECORD 的文档说 bKeyDown按下键时该值设置为真,释放键时该值设置为假,但这不是我观察到的行为。

什么可能导致这种情况?

编辑(4-19-2021):显然双击从这个脚本构建的 exe 工作正常。只有当我从命令提示符或 powershell 运行脚本时,它才会失去理智。

标签: c++windowsiouser-input

解决方案


推荐阅读