【问题标题】:Keyboard events: Is the order guaranteed?键盘事件:顺序有保证吗?
【发布时间】:2012-07-20 15:15:42
【问题描述】:

对于按下单个键,可以处理多个事件。

有:KeyDownKeyPressedKeyUp

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

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

上下文:

在我在旧版 C++ 应用程序中遇到一些按键事件问题之后 我用spy++ 检查了这些事件。在那里我看到订单有时似乎 不正确,keypressed 不会为每个 keydownkeyup 触发。

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

请注意,这不是多语言问题,但我很感兴趣这是否适用于 C++、Java 和 C#。

【问题讨论】:

  • 我认为是的?否则,此评论将变为:“I dulwo musame sey。wshteirO shti meomcnt lduow cebmeo。”
  • 我想知道它是否保证按下单个键,而不是一系列按键上升、按键下降等。它们保证是连续的。
  • 您当前的应用程序是用 C#、Java 和 C++ 组合编写的吗?我只能说,“哇”!我很高兴我不必维护它!
  • 问题出现在 C++ 应用程序中,但我也对 Java 和 C# 感兴趣。也许这是特定于语言的。为什么不维护呢?这是遗留代码,我只是好奇订单是否得到保证
  • 我认为KeyPressed 仅在产生字符时才会被触发。即死键和修饰键(可能还有一些与 IME 相关的东西)不会触发它。

标签: c# java c++ winapi keyboard


【解决方案1】:

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

例如,在 Windows 中,如果您按住某个键,您会在按键重复时看到 KeyDown 和/或 KeyPressed,在松开按键后会看到单个 KeyUp

编辑:

现在我想了想,不过...Windows 开始时只会将 WM_KEYDOWNWM_KEYUP 消息发布到您的窗口(并且只有当您有焦点时)。 WM_CHAR 消息(与 KeyPressed 类似的 Win32 消息)基于消息循环调用 TranslateMessage 时的消息发布。这意味着两件事:

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

此外,如 cmets 中所述,如果在按下键时焦点切换,您可能只会看到 KeyUpKeyDown。 (键状态在焦点切换之前就已经是这样了,Windows 可能不会告诉你。)死键(不自己生成字符的键)不会触发KeyPressed at全部(尽管它们通常会触发KeyUpKeyDown)。他们通常只是等待下一个真实角色并对其进行修改。

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

您可能还应该决定是要处理字符还是。我认为这是混乱的一部分;这两个实际上是不同的概念,大多数时候你只真正关心一个或另一个。据称,当您处理KeyPressed 事件时,Win32 会告诉您密钥代码,该事件的真正意图是告诉您输入了什么字符。 (它被称为WM_CHAR 而不是WM_KEYPRESS 是有原因的。:) 为什么.net 的KeyPressEventArgs 类型只有KeyChar 而不是KeyCode。)另外两个将键盘基本上视为一堆按钮。

【讨论】:

  • 那个,再加上死键。
  • 同样考虑app 1接收WM_KEYDOWN,app 2接收对应的WM_KEYUP。顺序是有保证的,但对这些消息做出尽可能少的假设仍然很重要。键盘输入非常敏感,如果开始感觉像是 hack,请不要继续这样做
  • 感谢您的全面回答!这正是我的想法,即无法做出任何假设!我不做任何假设。我个人喜欢听 WM_KEYDOWN 而不是 WM_CHAR,但这是遗留代码,我不会修复任何没有破坏的东西。
【解决方案2】:

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

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

这是 Windows 2.0 时代文档不完善的直接结果。

【讨论】:

  • 按这个顺序可能是 99.99%,但我可以依靠吗?
  • 您如何依赖官方文档中未明确表达的任何内容?
  • 这正是问题所在。我可以依靠它吗?它在官方文档中的某处有说明吗?也许winapi进来了。
  • 我从未在 MS 文档中看到过类似的内容。我敢打赌它不存在。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-09-27
  • 1970-01-01
  • 1970-01-01
  • 2019-08-25
  • 1970-01-01
  • 1970-01-01
  • 2020-09-27
相关资源
最近更新 更多