События клавиатуры: гарантируется ли порядок?
Для нажатия одной клавиши существует несколько событий, которые могут быть обработаны.
Есть: KeyDown
, KeyPressed
, KeyUp
.
Гарантируется ли, что приложение будет получать эти события в таком порядке?
Я имею в виду: это порядок одного события нажатия клавиши, а не последовательность различных нажатий клавиш.
Контекст:
После того, как у меня возникли некоторые проблемы с событиями нажатия клавиш в устаревшем приложении C++
Я изучал события с spy++
. Там я и увидел это. порядок, похоже, иногда
не быть правым и keypressed
не уволить за каждый keydown
или keyup
.
2 ответа:
Они должны происходить в таком порядке, когда они происходят, в большинстве приложений. Но ваше окно может не получать каждое событие для каждого введенного символа.
Например, в Windows, Если вы удерживаете клавишу, вы увидите
KeyDown
и/илиKeyPressed
несколько раз, когда ключ повторяется, и одинKeyUp
, когда ключ отпущен.Правка:
Однако теперь, когда я об этом думаю...Windows начинает публиковать только сообщенияWM_KEYDOWN
иWM_KEYUP
в вашем окне (и только если у вас есть фокус).WM_CHAR
сообщения (аналог Win32 дляKeyPressed
) публикуются на основе тех, когда цикл сообщений вызывает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
. :) И почему тип .netKeyPressEventArgs
имеет толькоKeyChar
, а неKeyCode
.) Другие два рассматривают клавиатуру как в основном кучу кнопок.
Если вы являетесь пользователем Windows, эмпирическое правило здесь таково: проверьте порядок событий путем регистрации или в отладчике, а затем предположите, что это будет всегда так.
Это не идеально, но это работает в 95% случаев. Я много раз слышал истории о том, что команда Windows всегда отталкивает назад, чтобы что-то изменить, потому что на 100% уверена, что это что-то сломает.
Это прямой результат плохой документации эпохи Windows 2.0.