2011-11-21 109 views
0

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

我正在处理输入的程序,使用SendInput()释放修改键(alt,ctrl等等),发送输入,然后重新按下修改键。

问题是,我不知道在发送输入后是否仍然按下修饰键,因为我发送了键入事件,并且上述两个函数都返回了键不管物理密钥的状态。因此,如果我假定它们仍然处于关闭状态,则用户将留下一个悬而未决的ctrl-down,直到用户再次按下并释放cntl(或任何修改键)为止。否则,即使物理键仍然关闭,键仍可能保留。

因此,有什么方法(最好没有任何太低的水平)来检测物理键状态。仅限Windows的方法很好。关键监控(听取关键事件)实际上是不可能的(或者至少真的,真的不可取)。

回答

0

经过多次测试,我似乎已经弄明白了。 MSDN约GetKeyState()

该函数返回的键状态随着线程从其消息队列中读取关键消息而发生更改。

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

演示此功能的简单测试是here(VS2010解决方案)或仅源here

+0

“GetAsyncKeyState()仍然适用于键上/下消息(不是物理键状态)”与[MSDN文档](http://msdn.microsoft.com/en-us/library/windows/desktop/ ms646293(v = vs.85).aspx) –

+0

这是无关紧要的。这是它的工作原理。一旦发布关键事件,GetAsyncKeyState()的返回值就会改变。 –

+0

他们的钥匙掉下来了,信息就发布了。是的,这几乎是发生了什么! –

0

你在这里有点困惑。实际上GetAsyncKeyState()确实在调用GetAsyncKeyState()的时刻返回关键状态。另一方面,GetKeyState()基于排队消息的历史返回关键状态。

+0

MSDN声称这同样的事情,但在测试中,它不成立。发送密钥注册事件后,无论物理密钥状态如何,GetAsyncKeyState()实际上都会报告密钥已启动。 (Win7 64-bit) –

+0

所以你认为一些基本的东西,因为这在Windows中被打破,没有人注意到了25年? –

+0

我知道在发送按键事件后会返回不正确的结果。 –

1

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

换句话说,您的代码有一个竞争条件,那就是你在观察什么。