c++ - 标准输入中的 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 运行脚本时,它才会失去理智。
解决方案
推荐阅读
- wordpress - 如何删除我的 wordpress 网站顶部的空白
- c - 为什么我的 while() 语句陷入无限循环?
- css - 在小型设备中,如何使用 bootstrap4 将顶部 div 放在底部,底部 div 放在顶部?
- ffmpeg - 使用ffmpeg复制时如何排除eia_608字幕?
- java - Akka如何连接source、flow和sink
- 32bit-64bit - 在 WebAssembly 中同时拥有 32 位和 64 位数字的基本原理是什么?
- ruby-on-rails - 录像机磁带导轨
- react-native - React-Native,组件间共享状态(react-native-router-flux)
- javascript - 使用 JavaScript 在窗口中获取当前查看的文本?
- sql - 对多列进行透视查询