作者:高俊伦丽成 | 来源:互联网 | 2023-05-17 13:21
Forpressingasinglekey,therearemultipleeventsthatcanbehandled.对于按下单个键,可以处理多个事件。Therei
For pressing a single key, there are multiple events that can be handled.
对于按下单个键,可以处理多个事件。
There is: KeyDown
, KeyPressed
, KeyUp
.
有:KeyDown,KeyPressed,KeyUp。
Is it guaranteed that an application will receive those events in that order?
是否保证应用程序将按该顺序接收这些事件?
What I mean is: is the order of a single key pressing event, not a series of different keys pressed.
我的意思是:是按下单个按键事件的顺序,而不是按下一系列不同的按键。
Context:
After I had some problems with keypress-events in a legacy C++ application I inspected the events with spy++
. There I saw that the order seems sometimes not to be right and the keypressed
is not fired for every keydown
or keyup
.
在我在遗留C ++应用程序中遇到keypress-events的一些问题之后,我用spy ++检查了事件。在那里,我看到订单似乎有时不正确,并且每次keydownor keyup都没有触发keypressed。
But, I was sure that the events should be fired in exactly that order, but could not find anything on the internet. So I came up with this question here.
但是,我确信事件应该按照那个顺序被触发,但是在互联网上找不到任何东西。所以我在这里提出了这个问题。
Please note that this is not a multiple languages problem, but I am interested whether this is true for C++, Java and C#.
请注意,这不是一个多语言问题,但我感兴趣的是CID,Java和C#是否正确。
2 个解决方案
4
They should happen in that order when they happen, in most apps. But your window might not receive every event for every character entered.
在大多数应用中,它们应该按顺序发生。但是,您输入的每个字符的窗口可能都不会收到任何事件。
For example, in Windows, if you hold down a key you'll see a KeyDown
and/or KeyPressed
repeatedly as the key repeats, and a single KeyUp
once the key is released.
例如,在Windows中,如果按住某个键,您将在键重复时重复看到KeyDown和/或KeyPressed,并在键释放后重复显示单个KeyUp。
Edit:
Now that i think about it, though...Windows starts out only posting WM_KEYDOWN
and WM_KEYUP
messages to your window (and only if you have focus). WM_CHAR
messages (the Win32 analogue to KeyPressed
) are posted based on those when the message loop calls TranslateMessage
. This means two things:
现在我考虑一下,但是...... Windows开始只向你的窗口发布WM_KEYDOWN和WM_KEYUP消息(只有你有焦点)。 WM_CHAR消息(Win32模拟到KeyPressed)基于消息循环调用TranslateMessage时发布的消息。这意味着两件事:
- If the window has a backlog of messages, the API might just add the message to the end of the queue (IDK); this makes more sense to me (the message queue being a queue, after all, and not a stack), but it does mean that if there is already a
WM_KEYUP
for that key in the queue (for example, if the user hit and released a key while another message was being processed), the corresponding WM_CHAR
might appear after it.
如果窗口有积压的消息,API可能只是将消息添加到队列的末尾(IDK);这对我来说更有意义(消息队列毕竟是一个队列,而不是堆栈),但它确实意味着如果队列中已存在该键的WM_KEYUP(例如,如果用户命中并释放当正在处理另一条消息时,一个密钥),相应的WM_CHAR可能会出现在它之后。
- Languages like C and C++ have more flexibility (read: less built-in automation) in how they handle messages; in order for them to get
WM_CHAR
messages, they have to either call TranslateMessage
explicitly or do the translation themselves (barring another app posting such messages to it). With the latter, there's no telling what order the messages will be posted in.
C和C ++等语言在处理消息方面具有更大的灵活性(读取:内置自动化程度更低);为了让他们获得WM_CHAR消息,他们必须明确地调用TranslateMessage或自己进行翻译(除非另一个应用程序向其发布此类消息)。对于后者,无法确定消息的发布顺序。
Also, as mentioned in the comments, if the focus switches while a key is down, you might only see a KeyUp
or KeyDown
. (The key state was already that way before the focus switch, and Windows probably won't tell you about it.) And dead keys (ones that don't generate a character on their own) won't trigger a KeyPressed
at all (though they do typically trigger KeyUp
and KeyDown
). They typically just wait for the next real character and modify it.
此外,如评论中所述,如果焦点在按键关闭时切换,您可能只会看到KeyUp或KeyDown。 (关键状态在焦点切换之前已经是这样了,Windows可能不会告诉你它。)死键(不能自己生成一个字符的键)根本不会触发KeyPressed(虽然他们通常会触发KeyUp和KeyDown)。他们通常只是等待下一个真正的角色并进行修改。
Short version of all that: You can rely on the order in which KeyDown
events appear in relation to each other. Same with KeyPressed
, and even KeyUp
. But, at least in Windows, the three message types are not really coordinated with each other. So don't assume that every KeyUp
will match a KeyDown
(or vice versa), or that KeyPressed
appears before KeyUp
.
所有这些的简短版本:您可以依赖KeyDown事件相对于彼此出现的顺序。与KeyPressed相同,甚至与KeyUp相同。但是,至少在Windows中,这三种消息类型并不真正相互协调。因此,不要假设每个KeyUp都与KeyDown匹配(反之亦然),或KeyPress出现在KeyUp之前。
You should probably also decide whether you want to process characters or keys. That's part of the confusion here, i think; the two are actually different concepts, and most of the time you only really care about one or the other. While Win32 would allegedly tell you the key code when you're handling a KeyPressed
event, the real intent of that event is to tell you what character was entered. (There's a reason it's called WM_CHAR
and not WM_KEYPRESS
. :) And why .net's KeyPressEventArgs
type only has a KeyChar
and not a KeyCode
.) The other two treat the keyboard as basically a bunch of buttons.
您可能还应该决定是否要处理字符或键。我认为这是混乱的一部分;这两者实际上是不同的概念,大多数时候你只关心其中一个。据称Win32会在您处理KeyPressed事件时告诉您关键代码,而该事件的真正意图是告诉您输入的字符。 (有一个原因,它被称为WM_CHAR而不是WM_KEYPRESS。:)为什么.net的KeyPressEventArgs类型只有KeyChar而不是KeyCode。)其他两个将键盘视为基本上是一堆按钮。