Как справиться с нажатой клавишей с логотипом Windows при использовании `SendInput`? - PullRequest
3 голосов
/ 26 мая 2010

Мое приложение синтезирует нажатия клавиш в других приложениях с помощью SendInput. Это почти работает, за исключением того, что из-за обстоятельств, которые я не могу изменить, левая клавиша Windows всегда будет физически нажата при отправке ввода. Это означает, что, например, если отправляемым нажатием клавиши является, например, клавиша «d», то Windows воспринимает нажатие клавиши как комбинацию клавиш Win + D и отображает рабочий стол, а нажатие клавиши «d» никогда не достигает назначенной цели.

В документации упоминается эта проблема, но разочаровывающе расплывчато в том, как ее исправить (выделено мной):

Эта функция не сбрасывает текущее состояние клавиатуры. Любые клавиши, которые уже были нажаты при вызове функции, могут мешать событиям, которые генерирует эта функция. Чтобы избежать этой проблемы, проверьте состояние клавиатуры с помощью функции GetAsyncKeyState и, при необходимости, исправьте .

Как мне "исправить по необходимости"?

Я пытался использовать SetKeyboardState, чтобы отключить состояние клавиатуры клавиши VK_LWIN, после первого присоединения моего потока к потоку окна, которому я посылаю нажатия клавиш (с помощью AttachThreadInput), но похоже, это никак не влияет на поведение.

Я также пытался вставить событие KEYEVENTF_KEYUP в начале ввода, который я посылаю с SendInput, но это вызывает всплывающее меню «Пуск» и захватывает фокус, что, очевидно, недопустимо.

Как правильно обращаться с нажатой клавишей с логотипом Windows при вызове SendInput?

EDIT:

Согласно @ ответу Брайана Я могу предотвратить вмешательство ключа выигрыша в мой код, установив низкоуровневый трюк, который перехватывает события нажатия клавиши win-key.

Это, однако, имеет нежелательный эффект, что ключ Windows теперь полностью отключен. Я могу в некотором роде предусмотреть какое-то решение этой проблемы, где я сохраняю информацию о состоянии всех клавиш в моем брелке и моделирую нажатия клавиш Windows при нажатии других клавиш, в зависимости от того, являются ли они теми, которые я использую. симуляция, но это звучит как взломать для меня. В качестве альтернативы, я мог бы использовать свой keyhook для эмуляции важных сочетаний клавиш Windows.

Но из документации следует, что все должно работать намного проще. Решение Брайана состоит в том, чтобы в первую очередь не дать клавише «выиграть» перейти в нажатое состояние. Но в документации говорится, что вы должны быть в состоянии проверить, нажата ли она позже, и исправить ее, если она есть.

Возможно ли это сделать?

Ответы [ 2 ]

3 голосов
/ 26 мая 2010

Я в основном решил эту проблему вчера :) Мой код написан на C #, но в основном он состоит из вызовов Win32 API через p / invoke, поэтому он должен транслироваться непосредственно в C ++.

Решение состоит в том, чтобы использовать Низкоуровневый хук клавиатуры для перехвата исходного события KeyDown ключа Windows (и сообщить ОС, что вы обработали его, чтобы он не был передан другим приложениям и / или ОС). Затем, в зависимости от ОС, смоделируйте событие KeyUp ключа Windows перед вашим вводом. Похоже, вы на полпути, вам просто нужно перехватить начальный KeyDown.

Мое решение предназначено для Windows Vista и Windows 7, поэтому, если вы работаете в XP или ниже, возможно, вам не нужно отправлять KeyUp. Это то, что я буду тестировать в ближайшее время, это может работать в обоих; однако Vista и 7 перехватывают ключ Windows более агрессивно, чем XP, поэтому я подозреваю.

0 голосов
/ 14 июня 2010

Для программы не существует более "простого" способа сделать это без изменения реестра. Идеальным решением является отслеживание нажатий клавиш в таблице (std :: map, Dictionary и т. Д.). Задача MS со стороны MS состоит в том, чтобы не дать вирусам / вредоносным программам захватить контроль над клавиатурой и запретить пользователю использовать важные комбинации клавиш, такие как WinKey-L и Ctrl-Alt-Delete.

Однако вы можете переназначить коды сканирования клавиатуры в реестре, если перехват клавиатуры не для вас. Это не идеально, так как трудно изменить (особенно, если вы допустили ошибку, или ваша программа вылетает, или пользователь удаляет приложение, но взлом реестра не отменяется). Но это работает. Вот несколько ссылок:

http://www.howtogeek.com/howto/windows-vista/map-any-key-to-any-key-on-windows-xp-vista/

http://www.howtogeek.com/howto/windows-vista/disable-caps-lock-key-in-windows-vista/

http://www.usnetizen.com/fix_capslock.php

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...