【问题标题】:winapi GetAsyncKeyState() does not work as described?winapi GetAsyncKeyState() 不像描述的那样工作?
【发布时间】:2018-05-31 15:59:50
【问题描述】:

根据microsoft's documentation,据说GetAsyncKeyState()

确定调用函数时按键是向上还是向下

我一直在构建一个 UI 自动化库,问题归结为这个

#include <Windows.h>
#include <iostream>
#include <chrono>
#include <thread>
using namespace std;

bool IsKeydownAsync(int key) {
    return GetAsyncKeyState(key) & 0x8000;
}

int main(){
    while (1) {
        if (IsKeydownAsync('A')) {
            cout << "triggered" << endl;
        }
        this_thread::sleep_for(chrono::milliseconds(10));
    }
}

所以我的理解是,我的应用程序是否处于焦点并不重要,GetAsyncKeyState() 应该始终返回物理键在被调用时是向上还是向下。

我已经在各种应用程序上对此进行了测试,并且在大多数情况下,它的行为与描述的一样。但是,在某些游戏中,这种行为会中断,并且不再报告键是向上还是向下。按住键时不会调用cout &lt;&lt; "triggered" &lt;&lt; endl。

有什么我忽略的吗?

【问题讨论】:

  • 请注意文档的返回值和备注部分。 GetAsyncKeyState 可能不是输入处理或 UI 自动化的最佳选择。你应该使用别的东西。
  • @VTT 返回值和备注部分仅提到 LSB 不可靠,但我仅测试 MSB 以查看密钥是否已关闭。我正在考虑使用 RAWINPUT,但这将是我最后的手段,因为我对它不太熟悉
  • @ShawnLi 您能否明确提及破坏行为的游戏?我是否理解正确:您在记事本中按 A 键,然后您的程序显示“已触发”,但如果您在您提到的某个游戏中按 A 键,则不再显示“已触发”?
  • 众所周知,游戏使用原始输入来读取键盘,在通过正常管道处理之前截取击键。这是一种非常便宜的反作弊方法,只能通过修补驱动程序来破解。

标签: c++ winapi keyboard


【解决方案1】:

自从我在 Windows 中使用本机输入已经有一段时间了,但根据经验,Windows API 函数只报告使用同步 Windows API 功能也报告的键状态,也就是说正常的应用程序消息/事件输入。

一些较旧的游戏使用以前版本的 DirectX 和其他方法来捕获输入,例如使用自 Windows 8.1 / 10 以来已弃用的名为 XInput(2) 的库。虽然支持轮询和事件/消息,但输入是使用 DirectX 线程捕获的,并且与 Windows API 相比处理方式完全不同。这样做的主要原因是操作系统试图迎合所有制造商,而 DirectX API 没有专门解决输入问题。

【讨论】:

  • 第一段仅适用于同步GetKeyState函数,不适用于GetAsyncKeyState。
  • GetAsyncKeyState 返回更多“关联中断级状态”信息,但仍流经相同的操作系统虚拟键层。听起来很奇怪,这仍然不同于驱动程序对您的键盘的了解,即 DirectInput / XInput 返回的内容。
  • 真的不想写驱动了……不过好像只有这个了
猜你喜欢
  • 2020-04-04
  • 2017-10-31
  • 2011-01-11
  • 1970-01-01
  • 2022-12-12
  • 1970-01-01
  • 1970-01-01
  • 2018-04-14
  • 2021-05-22
相关资源
最近更新 更多