键盘事件:订单是否有保证?

时间:2012-07-21 18:11:37

标签: c# java c++ winapi keyboard

要按一个键,可以处理多个事件。

KeyDownKeyPressedKeyUp

是否保证应用程序将按该顺序接收这些事件?

我的意思是:是一键按下事件的顺序,而不是按下一系列不同的按键。

上下文

在遗留C ++应用程序中遇到keypress-events时出现问题 我用spy++视察了这些事件。在那里,我看到订单似乎有时候 不正确,keypressedkeydown不会触发keyup

但是,我确信事件应该按照那个顺序被触发,但是 在互联网上找不到任何东西。所以我在这里提出了这个问题。

请注意,这不是多语言问题,但我对C ++,Java和C#是否属实感兴趣。

2 个答案:

答案 0 :(得分:4)

在大多数应用中,它们应该按顺序发生。但是,对于输入的每个字符,您的窗口可能不会收到每个事件。

例如,在Windows中,如果您按住某个键,则会在重复键时重复显示KeyDown和/或KeyPressed,并在键重复时显示一个KeyUp被释放。

编辑:

现在我考虑一下,但是...... Windows开始时只向您的窗口发布WM_KEYDOWNWM_KEYUP条消息(只有当您有焦点时)。 WM_CHAR消息(Win32类似于KeyPressed)根据消息循环调用TranslateMessage时的消息发布。这意味着两件事:

  • 如果窗口有积压的消息,API 可能只是将消息添加到队列末尾(IDK);这对我来说更有意义(消息队列毕竟是队列,而不是堆栈),但它确实意味着如果该密钥已经存在WM_KEYUP队列(例如,如果用户在处理另一条消息时点击并释放了一个键),相应的WM_CHAR可能会在之后出现
  • C和C ++等语言在处理消息方面具有更大的灵活性(读取:内置自动化程度更低);为了让他们获得WM_CHAR条消息,他们必须明确地调用TranslateMessage或自己进行翻译(除非另一个应用程序向其发布此类消息)。对于后者,无法确定消息的发布顺序。

此外,正如评论中所述,如果在关键功能关闭时焦点切换,您可能只会看到KeyUpKeyDown。 (关键状态在焦点切换之前已经是这样了,Windows可能不会告诉你它。)死键(不能自己生成字符的那些)不会触发{{1}完全(尽管它们通常会触发KeyPressedKeyUp)。他们通常只是等待下一个真正的角色并进行修改。

所有的简短版本:您可以依赖KeyDown事件相对于彼此出现的顺序。与KeyDown相同,甚至与KeyPressed相同。但是,至少在Windows中,这三种消息类型并不真正相互协调。因此,不要假设每个KeyUp都匹配KeyUp(反之亦然),或者KeyDown出现在KeyPressed之前。

您可能还应决定是否要处理字符。我认为这是混乱的一部分;这两者实际上是不同的概念,大多数时候你只关心其中一个。据称Win32会在您处理KeyUp事件时告诉您关键代码,但该事件的真正意图是告诉您输入的字符。 (这有一个原因叫它KeyPressed而不是WM_CHAR。:)为什么.net的WM_KEYPRESS类型只有KeyPressEventArgs而不是KeyChar。)其他两个对待键盘基本上是一堆按钮。

答案 1 :(得分:0)

如果您是Windows用户,这里的经验法则是:通过记录或在调试器中检查事件的顺序,然后假设这将始终如此。

这并不完美,但这在95%的情况下有效。我多次听过Windows团队总是推迟改变任何事情的故事,因为100%肯定会破坏某些东西。

这是Windows 2.0时代文档记录不佳的直接结果。