События клавиатуры: гарантируется ли порядок?
Для нажатия одной клавиши существует несколько событий, которые могут быть обработаны.
Есть: 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.