键盘事件:订单是否得到保证
Keyboard events: Is the order guaranteed?
对于按下单个键,可以处理多个事件。
有:KeyDown
、KeyPressed
、KeyUp
。
是否保证应用程序将按该顺序接收这些事件?
我的意思是:是单个按键事件的顺序,而不是按下的一系列不同键。
上下文:
在旧版C++应用程序中遇到按键事件问题后我用spy++
检查了事件.在那里我看到订单似乎有时不对,keypressed
不会每次keydown
或keyup
都被解雇.
我确信事件应该完全按照这个顺序触发,但是在互联网上找不到任何东西。所以我在这里提出了这个问题。
请注意,这不是一个多语言问题,但我对C++、Java 和 C# 是否如此感兴趣。
在大多数应用中,它们应该按该顺序发生。 但是,您的窗口可能不会收到输入的每个字符的每个事件。
例如,在 Windows 中,如果按住某个键,则在按键重复时会看到KeyDown
和/或KeyPressed
,并在释放键后看到单个KeyUp
。
编辑:
不过,现在我想起来了...Windows 开始时仅将WM_KEYDOWN
和WM_KEYUP
消息发布到窗口(并且仅当您具有焦点时(。 WM_CHAR
消息(类似于 KeyPressed
的 Win32 (基于消息循环调用 TranslateMessage
时的消息发布。 这意味着两件事:
- 如果窗口有消息积压,API 可能只是将消息添加到队列末尾 (IDK(; 这对我来说更有意义(毕竟消息队列是一个队列,而不是一个堆栈(,但它确实意味着如果队列中已经有该键的
WM_KEYUP
(例如, 如果用户在处理另一条消息时按下并释放了某个键(,则相应的WM_CHAR
可能会出现在它之后。 - 像C和C++这样的语言在处理消息方面具有更大的灵活性(阅读:内置自动化较少(;为了获得
WM_CHAR
消息,它们必须显式调用TranslateMessage
或自己进行翻译(除非其他应用程序向其发布此类消息(。 对于后者,不知道消息将以什么顺序发布。
此外,如评论中所述,如果在按下键时焦点切换,您可能只看到KeyUp
或KeyDown
。 (在焦点切换之前,键状态已经是这样了,Windows 可能不会告诉你。 死键(不会自行生成角色的键(根本不会触发KeyPressed
(尽管它们通常会触发KeyUp
和KeyDown
(。 他们通常只是等待下一个真实角色并对其进行修改。
所有这些的简短版本:您可以依赖KeyDown
事件彼此相关的显示顺序。 与KeyPressed
相同,甚至KeyUp
。 但是,至少在Windows中,这三种消息类型并没有真正相互协调。 因此,不要假设每个KeyUp
都匹配一个KeyDown
(反之亦然(,或者KeyPressed
出现在KeyUp
之前。
您可能还应该决定是要处理字符还是键。 我认为,这是这里混乱的一部分;这两者实际上是不同的概念,大多数时候你只真正关心一个或另一个。 据称,Win32会在您处理KeyPressed
事件时告诉您密钥代码,但该事件的真正目的是告诉您输入了什么字符。 (它被称为WM_CHAR
而不是WM_KEYPRESS
是有原因的。 :) 以及为什么 .net 的 KeyPressEventArgs
类型只有KeyChar
而不是KeyCode
。 另外两个将键盘视为一堆按钮。
如果您是 Windows 用户,这里的经验法则是:通过日志记录或在调试器中检查事件的顺序,然后假设这将始终如此。
这并不完美,但这在 95% 的情况下都有效。我多次听到这样的故事:Windows团队总是推迟改变任何东西,因为100%确定这会破坏某些东西。
这是Windows 2.0时代文档不佳的直接结果。
- 如果事件在仍在执行时再次设置,RegisterWaitForSingleObject 是否会并行运行回调?
- 创建的事件数量是否有限制?
- 是否可以在QT GUI应用程序中处理事件时播放加载动画指示器?
- 是否可以在C++(17)中捕获某些对象属性的破坏性赋值事件
- epoll_wait() 是否报告所有关闭的套接字事件
- 是否有任何可能的方法将事件(自定义)附加到在运行时创建的对象?[C 构建器]
- 在使用 Poll() 的 TCP 服务器 - 客户端连接中,我是否需要手动设置事件?我从来没有到达 POLLOUT 来写
- 是否可以捕获全局鼠标事件
- 是否可以使用 select(2) 来监视 SDL 文本输入事件
- 是否有任何对象可以用作FIFO和弹出数据的事件
- 是否可以在 wxFrame 中捕获鼠标事件
- 如何调试是否设置了 Windows 事件对象
- 是否可以触发由 Minko 中的 HTML 事件启动的 C++ 代码
- 键盘事件:订单是否得到保证
- Qt表单中是否有更改事件
- 是否可以在不调用 QApplication::exec() 的情况下创建本地事件循环
- 是否可以在 MFC 按钮控件上检测到鼠标右键单击事件
- 是否可以捕获翻译/调度消息循环中的窗口消息/事件
- ZeroMQ是否有数据到达时的通知/回调事件/消息
- 如何在VC++中不使用.NET Framework来确定特定事件日志是否存在