Клавиша SHIFT неправильно определяется в состоянии клавиатуры при использовании перехвата клавиатуры Windows

Я работаю со считывателем магнитных карт.

При подключении к USB-порту и открытии Блокнота я получаю следующий правильный результат:

%B4290071074381429^NAZARKO/C M               ^1302101000002024976000000000002?;4290071074381429=13021010000020204976?

Когда я использую перехватчик клавиатуры (написанный на C#), который вызывает функции Windows API, я получаю противоречивые результаты, например:

%B42()071074381429^NAZARKO/C M               ^1302101000002024976000000000002?;4290071074381429=13021010000020204976?

Как видите, здесь проблема в том, что первая цифра «90» становится «()», как если бы при нажатии клавиш «9» и «0» была нажата клавиша SHIFT.

Код хука клавиатуры взят отсюда (Keyboard.cs): https://nappybar.googlecode.com/svn/Keyboard.cs и настраивается следующим образом:

            _kbHook = new KeyboardHook();
            _kbHook.KeyIntercepted += KeyboardHook_KeyIntercepted;
            _kbHook.SetParameters(KeyboardHook.Parameters.AllowAltTab);
            _kbHook.SetParameters(KeyboardHook.Parameters.PassAllKeysToNextApp);

Как указано выше, результаты, которые я получаю при использовании этого с картридером, противоречивы. Похоже, что состояние клавиатуры из (GetKeyboardState) не совсем правильное. В основном, иногда пишет, что SHIFT нажат, когда этого не должно быть, и наоборот. http://msdn.microsoft.com/en-us/library/windows/desktop/ms646299(v=vs.85).aspx

Кто-нибудь знает, почему это происходит и почему он работает правильно в Блокноте? И что еще более важно, как я могу это исправить/обойти? Спасибо.


person user1579177    schedule 06.08.2012    source источник


Ответы (1)


Вы используете низкоуровневый клавиатурный хук, который запускается в потоке. Поэтому, когда вы вызываете GetKeyboardState, вы получаете состояние своей собственной локальной клавиатуры, а не состояние клавиатуры Блокнота. Если вы хотите продолжить движение по этому маршруту, вам нужно отслеживать состояния клавиши Shift вручную. Почему бы просто не обрабатывать обычные сообщения клавиатуры в вашем приложении? Зачем нужен глобальный хук? Если вы обработаете их нормально, то произойдет обработка клавиши Shift, и при вызове GetKeyboardState вы увидите соответствующие состояния клавиш. Преобразование необработанных действий клавиатуры в печатные символы общеизвестно сложно. В дополнение к состояниям клавиш Shift вам нужно беспокоиться о Caps Lock и IME.

person Raymond Chen    schedule 06.08.2012
comment
Спасибо за Ваш ответ. Приложение работает как киоск с несколькими приложениями, и мы хотим обнаруживать все нажатия клавиш (или ввод считывателя), отсюда и хук. Ручное обнаружение SHIFT, казалось, решило проблему. - person user1579177; 06.08.2012
comment
К счастью для вас, это киоск, где вы управляете клавиатурой и можете убедиться, что она на английском языке. Состояния сдвига в других языках намного сложнее. (Обратите внимание, что даже в американском английском вам нужно беспокоиться о Caps Lock, Ctrl, Alt и Num Lock.) - person Raymond Chen; 06.08.2012
comment
Просто используйте GetAsyncKeyState. Он будет правильно получать значения клавиш-модификаторов (shift, control, alt) независимо от того, какое окно активно. GetKeyboardState не может получить их из-за проблем с потоками. С другой стороны, GetAsyncKeyState получает физические свойства клавиш, поэтому он не будет возвращать состояние переключения Caps, Num и Scroll. После прохода по всем ключам с помощью GetAsyncKeyState (заполнение массива байтов) вызовите GetKeyState для блокировки заглавных букв, прокрутки и num и проверьте их бит переключения (наименее значащий бит) и перезапишите значения в основном массиве. - person Triynko; 25.06.2015