为啥在 Win32 中使用 `GetAsyncKeyState()` 时我的热键会出错?

Posted

技术标签:

【中文标题】为啥在 Win32 中使用 `GetAsyncKeyState()` 时我的热键会出错?【英文标题】:Why are my hotkeys bugging out when using `GetAsyncKeyState()` in Win32?为什么在 Win32 中使用 `GetAsyncKeyState()` 时我的热键会出错? 【发布时间】:2013-11-05 07:13:58 【问题描述】:

main.c:

#include <stdio.h>
#include <windows.h>
#include <stdbool.h>

int main(void) 
    while (true) 
        if (GetAsyncKeyState(VK_CONTROL)) 
            if (GetAsyncKeyState('1')) 
                printf("Set grenades to 100!\n");
                Sleep(500);
            
        

        Sleep(100);
    

    return 0;

我尝试在调试和发布模式之间、mingw 和 VS 编译器之间进行切换,但我对 C 和 C++ 都感到厌烦。在所有情况下都会发生相同的错误。

这个想法是让热键是 Control + 1。每当用户同时按下 Control 键和 1 键时,我希望运行代码 printf("Set grenades to 100!\n");

但是,有一个错误。如果用户按下并释放 1 键。等待任意时间(秒、分钟),然后按下 Control 键,printf("Set grenades to 100!\n"); 被执行。

即使用户在两者之间按下键,也会发生此错误。例如:printf("Set grenades to 100!\n"); 会在用户执行以下操作时执行:

    按 1 键。 释放 1 键。 按下并释放以下键:'H'、'i'、'S'、't'、'a'、'c'、'k'、'o'、'v'、'e'、 'r'、'f'、'l'、'o'、'w' 和 '2'。 按下并释放控制键。

在第 4 步,执行代码。如何修复此错误?

我想使用 GetAsyncKeyState 而不是 GetKeyState,因为我希望即使用户切换到另一个程序也能捕获输入。

【问题讨论】:

我不熟悉GetAsyncKeyState,但复合if 语句是否有效? if(GetAsyncKeyState(VK_CONTROL) &amp;&amp; GetAsyncKeyState('1'))? 我不想使用复合 if 语句,因为我有多个要使用的热键。 Control + 1、Control + 2、Control + 3 等...我会尝试看看是否修复了这个错误。 GetAsyncKeyState 的结果应该用 0x8000 屏蔽以检查密钥是否已关闭(根据文档)。无论如何,可以使用RegisterHotKey 设置热键。 即使我使用复合 if 语句,该错误似乎仍然存在。 GetAsyncKeyState 回答了“这个键现在按下了吗?”的问题,而不是它们是否同时按下、中间是否按下了任何键或一只猫的问题在你的键盘上。如果您需要跟踪这些事情,您需要自己提供额外的逻辑或选择不同的输入处理方法。 【参考方案1】:

关于GetAsyncKeyState()的返回值,根据Microsoft如果设置了最高位按键已按下。 这里的一个重要结论是:对于带符号的类型,例如short当设置最高有效位时,它被读取为负数GetAsyncKeyState() 返回short

这表明您的代码中用于解释GetAsyncKeyState() 结果的逻辑与其当前应用程序中需要的逻辑相反。也就是说,您的条件语句应该检查负数而不是正数。

还有一点说明:正如其他人所建议的,GetAsyncKeyState() 的目的是检查密钥的状态现在。但它的返回值还包含确定该键是否最近被按下的信息。事实上,这就是您通过查看 LSB 所做的事情。在同一链接中,解释了 LSB 是 最近 状态的指示器,但这不是推荐的做法。 recent 位状态可以由运行在另一个线程中的任何进程随时设置,因此,应谨慎使用。

所以,试试这个吧。我在 64 位窗口上测试过,它似乎工作正常,无论我先按多少次 1 或按ctrl 键,都不会出现弹出窗口。但是,当我同时按下两者时,它会弹出。

#include <stdio.h>
#include <windows.h>
//#include <stdbool.h>//I did not need this, you might.

int main(void) 
    while (1) 
    
        if (GetAsyncKeyState(VK_CONTROL)<0) 
        

            if (GetAsyncKeyState('1')<0) 
            
                printf("Set grenades to 100!\n");
                Sleep(200);//changed here for my test, you might need to change again
            
        
        Sleep(200);//changed here for my test, you might need to change again
                                          

    return 0;//unreachable code warning

【讨论】:

以上是关于为啥在 Win32 中使用 `GetAsyncKeyState()` 时我的热键会出错?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Git 命令在 Windows 10 上通过 Win32-OpenSSH 失败?

WIN32显示图片,为啥不显示?

为啥我的编辑控件在没有使用 MFC 的 win32 c++ 应用程序中看起来很奇怪?

Win32:为啥我的 PRINTDLG(或 PRINTDLGEX)有灰色背景?

为啥使用 Win32_PrintJob/C# 得到错误的 N-Up 打印总页数?

为啥老是有win32.troj.undef这个病毒?????