Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Состояние физического ключа

Автор вопроса: Chad SchougginsОтветов: 3

Две функции состояния ключа в API WIndows, GetKeyState() и GetAsyncKeyState(), определяют состояние ключа на основе сообщений о включении/отключении ключа, а не на физическом состоянии ключа.

Я работаю над программой, которая манипулирует вводом, используя SendInput(), чтобы отпустить клавиши-модификаторы (alt, ctrl и т. д.), отправить ввод, а затем повторно нажать клавиши-модификаторы.

Проблема в том, что я не знаю, нажаты ли клавиши-модификаторы после отправки ввода, потому что я отправил событие нажатия клавиши, и обе вышеупомянутые функции возвращают, что клавиша нажата независимо от состояния физического ключ. Поэтому, если я предполагаю, что они все еще не работают, пользователь остается с оборванным ctrl-down, вызывающим проблемы, пока пользователь снова не нажмет и не отпустит cntl (или любую клавишу-модификатор). В противном случае ключ может оставаться нажатым, даже если физический ключ все еще нажат.

Итак, есть ли способ (желательно без чего-либо слишком низкого уровня) определить состояние физического ключа. Методы только для Windows подходят. Мониторинг клавиш (прослушивание событий нажатия клавиш) на самом деле невозможен (или, по крайней мере, действительно не предпочтителен).

windowsinputkeyboardkeyboard-eventswinapi

Ответы

Ответ 1 · рейтинг 1 · Raymond Chen

Вы не даете оконному менеджеру достаточно времени для обработки ввода, который вы только что ввели. Пока не будет достигнута часть кода "обновить состояния ключей для GetAsyncKeyState", GetAsyncKeyState будет сообщать о старом значении. (В частности, он не достигнет этой точки, пока все низкоуровневые перехватчики клавиатуры не получат возможность проверить действие и, возможно, отклонить его.)

Другими словами, ваш код имеет состояние гонки, и это то, что вы наблюдаете.

Ответ 2 · David Heffernan

Вы тут немного путаетесь. На самом деле GetAsyncKeyState() возвращает состояние ключа в момент вызова GetAsyncKeyState(). С другой стороны, GetKeyState() возвращает состояние ключа на основе истории сообщений в очереди.

Ответ 3 · Chad Schouggins

После долгих испытаний я, кажется, понял это. MSDN сообщает о GetKeyState() :

Состояние ключа, возвращаемое этой функцией, изменяется по мере того, как поток считывает ключевые сообщения из своей очереди сообщений.

GetAsyncKeyState() по-прежнему работает с сообщениями о включении/выключении клавиш (не о состоянии физической клавиши), однако он просто не ждет, пока сообщение будет прочитано. Таким образом, если сообщение о ключевом событии отправлено через SendInput(), оно все равно вернет неверный результат - на самом деле, оно будет неверным до GetKeyState(), потому что оно будет неверным сразу после вызова.

Простой тест для демонстрации этой функциональности находится здесь (решение VS2010) или просто исходный код здесь.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы