2

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

有:KeyDown, KeyPressed, KeyUp.

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

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

语境:

在遗留 C++ 应用程序中的按键事件出现一些问题后,我使用spy++. 在那里我看到命令似乎有时不正确,并且keypressed不是每个keydownor都被解雇keyup

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

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

4

2 回答 2

4

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

例如,在 Windows 中,如果您按住一个键,您将看到一个KeyDown和/或KeyPressed在该键重复时重复出现,而KeyUp一旦松开该键,您将看到一个。

编辑:

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

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

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

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

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

于 2012-07-21T19:47:16.953 回答
0

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

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

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

于 2012-07-21T19:40:20.010 回答