【发布时间】:2012-08-25 20:57:53
【问题描述】:
我看到许多答案建议使用Keyboard.Modifiers 来确定@987654323@ 事件是否适用于具有修饰符集的键。不幸的是,因为Keyboard.Modifiers 返回修饰符的当前状态(而不是按下键时修饰符的状态),这会导致快速打字者非常烦人的间歇性错误。
具体来说,假设有人按下 Ctrl+A,然后在按下 A 几毫秒后松开 Ctrl。现在假设系统负载很重;密钥处理程序开始执行但被抢占了 50 毫秒。当键处理程序再次执行时,Ctrl 的 当前 状态为“已释放”。键处理程序现在会认为在没有 Ctrl 的情况下按下了“A”,这是错误。
类似地,如果快速打字员输入 A、Ctrl+End 并且我的应用程序使用 Keyboard.Modifiers,它最终可能会观察到 Ctrl+A...
在 WinForms 中,KeyDown 事件告诉我 Ctrl 确切的状态,即使在处理事件时它已经释放。如何在 WPF 中获得相同的行为?
编辑:Keyboard.Modifiers 可能实际上并未检索“当前”修饰键,而是检索与当前正在处理的按键消息相关的修饰键。在 WinAPI 中,这是“异步”和非异步键状态函数之间的区别。不幸的是,the documentation 没有提到“当前”的确切含义。如果有人知道,请说出来。
【问题讨论】:
-
你确定吗?我在 msdn 上找不到任何提示,这将证明你的理论......这真的很奇怪,处理程序参数不包括最初按下的键......如果你绑定到“onkeyDown”并且用户按下CONTROL(按住)然后a,然后释放CONTROL,该事件将被触发2次!首先仅使用“Control”,然后使用 CONTROL+A...有点奇怪--恕我直言,我们可以通过 thread.sleep 轻松解决...我现在必须启动 VS 吗? ;)
-
@TheHe 处理程序参数包括最初按下的键,但不包括修饰键信息。在良好的旧 WinAPI 中,修饰键与消息一起传递。在 WinForms 中也会发生同样的情况。该文档实际上警告您不要尝试处理 current 状态;例如,如果应用程序由于任何原因(例如 HDD 抖动)没有响应,则可能会在事后 秒 调用处理程序。