在大多数应用程序中,它们应该在发生时按顺序发生。但是您的窗口可能不会收到输入的每个字符的每个事件。
例如,在 Windows 中,如果您按住一个键,您将看到一个KeyDown
和/或KeyPressed
在该键重复时重复出现,而KeyUp
一旦松开该键,您将看到一个。
编辑:
不过,现在我考虑了一下……Windows 开始时只会向您的窗口发布WM_KEYDOWN
和WM_KEYUP
消息(并且只有当您有焦点时)。 WM_CHAR
消息(Win32 的类似物KeyPressed
)基于消息循环调用时的消息发布TranslateMessage
。这意味着两件事:
- 如果窗口有消息积压,API可能只是将消息添加到队列的末尾 (IDK);这对我来说更有意义(消息队列毕竟是一个队列
WM_KEYUP
,而不是堆栈),但这确实意味着如果队列中已经有一个 for 该键(例如,如果用户点击并释放了一个键,而另一条消息正在处理),相应的WM_CHAR
可能会出现在它之后。
- 像 C 和 C++ 这样的语言在处理消息方面具有更大的灵活性(阅读:更少的内置自动化);为了让他们获得
WM_CHAR
消息,他们必须明确调用TranslateMessage
或自己进行翻译(除非另一个应用程序向其发布此类消息)。对于后者,不知道消息将以什么顺序发布。
此外,如评论中所述,如果在按下键时焦点切换,您可能只会看到 aKeyUp
或KeyDown
。(键状态在焦点切换之前就已经是这样了,Windows 可能不会告诉你。)死键(不自己生成字符的键)根本不会触发 a KeyPressed
(尽管它们通常会触发KeyUp
和KeyDown
)。他们通常只是等待下一个真实角色并对其进行修改。
所有这些的简短版本:您可以依赖KeyDown
事件彼此相关的出现顺序。与 相同KeyPressed
,甚至KeyUp
。但是,至少在 Windows 中,这三种消息类型并没有真正相互协调。所以不要假设 everyKeyUp
会匹配 a KeyDown
(反之亦然),或者KeyPressed
出现在KeyUp
.
您可能还应该决定是否要处理字符或键。我认为这是混乱的一部分;这两个实际上是不同的概念,大多数时候你只真正关心一个或另一个。虽然 Win32 据称会在您处理事件时告诉您关键代码,但该KeyPressed
事件的真正意图是告诉您输入了什么字符。(它被称为WM_CHAR
而不是WM_KEYPRESS
.:) 以及为什么 .net 的KeyPressEventArgs
类型只有 aKeyChar
而没有 a KeyCode
。)另外两个将键盘基本上视为一堆按钮。