Windows 物理密钥状态

Windows 物理密钥状态,windows,winapi,input,keyboard,keyboard-events,Windows,Winapi,Input,Keyboard,Keyboard Events,WIndows API中的两个键状态函数,GetKeyState()和GetAsyncKeyState(),都基于键向上/向下消息而不是键的物理状态来确定键状态 我正在编写一个程序,该程序使用SendInput(),操作输入,释放修改键(alt、ctrl等),发送输入,然后重新按下修改键 问题是,我不知道在发送输入后修改键是否仍被按下,因为我已发送key up事件,并且无论物理键的状态如何,上述两个函数都会返回key up。因此,如果我假设它们仍然处于关闭状态,那么用户将保持按住ctrl键的悬空

WIndows API中的两个键状态函数,
GetKeyState()
GetAsyncKeyState()
,都基于键向上/向下消息而不是键的物理状态来确定键状态

我正在编写一个程序,该程序使用
SendInput()
,操作输入,释放修改键(alt、ctrl等),发送输入,然后重新按下修改键

问题是,我不知道在发送输入后修改键是否仍被按下,因为我已发送key up事件,并且无论物理键的状态如何,上述两个函数都会返回key up。因此,如果我假设它们仍然处于关闭状态,那么用户将保持按住ctrl键的悬空状态,从而导致出现问题,直到用户再次按下并释放cntl(或任何修改键)。否则,即使物理键仍处于关闭状态,也可能会保留向上键


因此,是否有任何方法(最好没有太低的级别)来检测物理密钥状态。仅限Windows的方法很好。密钥监视(监听密钥启动事件)实际上是不可能的(或者至少确实不可取)。

您在这里有点困惑。事实上,
GetAsyncKeyState()
确实会在调用
GetAsyncKeyState()
时返回密钥状态。另一方面,
GetKeyState()
根据排队消息的历史记录返回密钥状态。

您在这里有点困惑。事实上,
GetAsyncKeyState()
确实会在调用
GetAsyncKeyState()
时返回密钥状态。另一方面,
GetKeyState()
根据排队消息的历史记录返回密钥状态。

经过大量测试,我似乎已经找到了答案。MSDN说明了关于
GetKeyState()

当线程从其消息队列中读取密钥消息时,此函数返回的密钥状态将发生变化

GetAsyncKeyState()
仍然可以处理向上/向下键消息(不是物理键状态),但是,它不会等待消息被读取。因此,如果通过
SendInput()
发送密钥事件消息,它仍然会返回错误-事实上,在
GetKeyState()
之前它是不正确的,因为调用之后它会立即不正确


演示此功能的一个简单测试是(VS2010解决方案)或只是源代码。

经过多次测试,我似乎已经找到了答案。MSDN说明了关于
GetKeyState()

当线程从其消息队列中读取密钥消息时,此函数返回的密钥状态将发生变化

GetAsyncKeyState()
仍然可以处理向上/向下键消息(不是物理键状态),但是,它不会等待消息被读取。因此,如果通过
SendInput()
发送密钥事件消息,它仍然会返回错误-事实上,在
GetKeyState()
之前它是不正确的,因为调用之后它会立即不正确


演示此功能的一个简单测试是(VS2010解决方案)或仅仅是源代码。

您没有给窗口管理器足够的时间来处理刚刚注入的输入。在到达代码的“更新
GetAsyncKeyState
的密钥状态”部分之前,
GetAsyncKeyState
将报告旧值。(特别是,在所有低级键盘挂钩都有机会检查操作并可能拒绝操作之前,它不会达到这一点。)


换句话说,您的代码有一个竞争条件,这就是您所观察到的。

您没有给窗口管理器足够的时间来处理刚刚注入的输入。在到达代码的“更新
GetAsyncKeyState
的密钥状态”部分之前,
GetAsyncKeyState
将报告旧值。(特别是,在所有低级键盘挂钩都有机会检查操作并可能拒绝操作之前,它不会达到这一点。)


换句话说,您的代码有一个竞态条件,这就是您所观察到的。

MSDN声称这一点,但在测试中,它并不成立。在发送密钥启动事件后,无论物理密钥状态如何,GetAsyncKeyState()实际上都会报告密钥已启动。(Win7 64位)那么您认为Windows中出现了一些基本问题,25年来没有人注意到?我知道它在发送密钥更新事件后会返回错误的结果。在这种情况下,您似乎发现了一个错误。请向MS.提交一份bug报告。请记住包括一个完整的工作代码示例,以演示您发现的问题。@ChadSchouggins;使用GetAsyncKeyState时,请确保仅检查SHORT的高位以检查密钥状态。一个非常常见的错误是检查低位或只是检查总值是否为非零,这将导致错误的结果。有关详细信息,请参阅MSDN。这与GetKeyState()不同,在GetKeyState()中,您通常只需与零进行比较即可获得成功;你们不能用另一个代替一个。MSDN声称这是同样的事情,但在测试中,它并不成立。在发送密钥启动事件后,无论物理密钥状态如何,GetAsyncKeyState()实际上都会报告密钥已启动。(Win7 64位)那么您认为Windows中出现了一些基本问题,25年来没有人注意到?我知道它在发送密钥更新事件后会返回错误的结果。在这种情况下,您似乎发现了一个错误。请向MS.提交一份bug报告。请记住包括一个完整的工作代码示例,以演示您发现的问题。@ChadSchouggins;使用GetAsyncKeyState时,请确保仅检查SHORT的高位以检查密钥状态。一个非常常见的错误是检查低位或只是检查总值是否为非零,这将导致错误的结果。有关详细信息,请参阅MSDN。这与GetKeyState()不同,在GetKeyState()中,您通常只需比较