简体   繁体   English

键盘事件:顺序得到保证吗?

[英]Keyboard events: Is the order guaranteed?

For pressing a single key, there are multiple events that can be handled. 按下一个键,可以处理多个事件。

There is: KeyDown , KeyPressed , KeyUp . 有: KeyDownKeyPressedKeyUp

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++ . 在遗留C ++应用程序中的按键事件遇到一些问题之后,我用spy++检查了这些事件。 There I saw that the order seems sometimes not to be right and the keypressed is not fired for every keydown or keyup . 在那里,我看到的是,为了看起来有时不是正确的和keypressed不闪光时,每keydownkeyup

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#. 请注意,这不是多种语言的问题,但是我对C ++,Java和C#是否适用很感兴趣。

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). 现在,我考虑了一下,但是... Windows开始仅将WM_KEYDOWNWM_KEYUP消息发布到您的窗口(并且只有在您有焦点的情况下)。 WM_CHAR messages (the Win32 analogue to KeyPressed ) are posted based on those when the message loop calls TranslateMessage . 根据消息循环调用TranslateMessage时的消息发布WM_CHAR消息(类似于KeyPressed )。 This means two things: 这意味着两件事:

  • If the window has a backlog of messages, the API might just add the message to the end of the queue (IDK); 如果窗口中有消息积压,那么API 可能只是将消息添加到队列的末尾(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. 这对我来说更有意义(消息队列毕竟是队列 ,而不是堆栈),但这的确意味着如果队列中已有该键的WM_KEYUP (例如,用户按下并释放)一个键,而另一个消息正在处理中),相应的WM_CHAR可能会出现后面
  • Languages like C and C++ have more flexibility (read: less built-in automation) in how they handle messages; 诸如C和C ++之类的语言在处理消息方面具有更大的灵活性(阅读:内置自动化程度较低)。 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). 为了让他们获取WM_CHAR消息,他们必须显式调用TranslateMessage或自己进行翻译(除非另一个应用向其发布此类消息)。 With the latter, there's no telling what order the messages will be posted in. 对于后者,不会告诉您消息将以什么顺序发布。

Also, as mentioned in the comments, if the focus switches while a key is down, you might only see a KeyUp or KeyDown . 另外,如注释中所述,如果在按下某个键时焦点切换了,则可能只会看到KeyUpKeyDown (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 ). (键状态在焦点切换之前就已经是那样了,Windows可能不会告诉您。)而且,死键(那些不会自行生成字符的键)根本不会触发KeyPressed (尽管它们通常会触发KeyUpKeyDown )。 They typically just wait for the next real character and modify it. 他们通常只是等待下一个真实角色并对其进行修改。

Short version of all that : You can rely on the order in which KeyDown events appear in relation to each other. 所有内容的简短说明 :您可以依赖KeyDown事件相对于彼此出现的顺序。 Same with KeyPressed , and even KeyUp . KeyPressed甚至KeyUp But, at least in Windows, the three message types are not really coordinated with each other. 但是,至少在Windows中,这三种消息类型并没有真正相互协调。 So don't assume that every KeyUp will match a KeyDown (or vice versa), or that KeyPressed appears before KeyUp . 因此,请不要假定每个KeyUp都将匹配一个KeyDown (反之亦然),或者不要假设KeyPressed出现在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. 据称Win32在处理KeyPressed事件时会告诉您键码,但该事件的真正目的是告诉您输入了什么字符 (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. (有一个原因,它被称为WM_CHAR而不是WM_KEYPRESS 。:)以及为什么.net的KeyPressEventArgs类型仅具有KeyChar而不具有KeyCode 。)其他两个将键盘基本上视为一堆按钮。

If you are Windows user, the rule of thumb here is: check the order of events by logging or in debugger and then assume that this will be always so. 如果您是Windows用户,这里的经验法则是:通过记录日志或在调试器中检查事件的顺序,然后假定情况总是如此。

This is not perfect, but this works in 95% of cases. 这并不完美,但这在95%的情况下都有效。 I many times heard stories that Windows team always pushes back to change anything because 100% sure this will break something. 我无数次听到Windows团队总是回击更改任何事情的故事,因为100%确保这会破坏某些东西。

This is direct result of poor documentation of the Windows 2.0 era. 这是Windows 2.0时代文档不完善的直接结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM