Как определить наличие цифровой клавиатуры и как получить код сканирования для клавиши ввода цифровой клавиатуры?

Я хотел бы добавить в мою программу определенное поведение, которое привязывает функцию к клавише ввода с цифровой клавиатуры, если она есть, или привязывает альтернативную клавишу, если ее нет.

По словам Microsoft:

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

(источник)

Я знаю, что на моей клавиатуре это 0x9C (156), но это гарантировано для всех клавиатур.

Я не могу использовать MapVirtualKey() с VK_RETURN а также MAPVK_VK_TO_VSC так как это всегда возвращает код сканирования для основной клавиши возврата в центре клавиатуры.

Как я могу получить эту информацию без какого-либо вмешательства со стороны пользователя?

Мой язык - C/C++, и это только для Win32.

4 ответа

Для того, чтобы Numpad Enter распознавался как любой из видов Enter, аппаратное обеспечение клавиатуры должно отправить скан-код, который соответствует VK_RETURNв текущей раскладке клавиатуры. Раскладка клавиатуры определяется настройками системы и окном, в которое вводится клавиатура (или пользователем), а не физической клавиатурой. Вполне возможно, что раскладка виртуальной клавиатуры не соответствует физической клавиатуре (т. Е. Надписи на клавишах не соответствуют их функциям).

Есть две стратегии, позволяющие правильно работать с разными физическими раскладками клавиатуры:

  1. Измените метки, видимые на клавишах, но сохраните коды сканирования в тех же физических положениях. Чтобы функция каждой клавиши соответствовала ее метке, пользователь должен выбрать, установить или создать правильную раскладку клавиатуры в программном обеспечении.
  2. Физически перемещайте клавиши или присваивайте заранее установленные коды сканирования различным физическим позициям. ОС не знает и не заботится о том, где физически находится ключ; он просто отображает коды сканирования на виртуальные коды клавиш на основе текущей раскладки клавиатуры.

И Enter, и Numpad Enter отображаются на VK_RETURN; для Numpad Enter нет виртуального кода клавиши, поэтому у него нет возможности иметь разные коды сканирования на разных раскладках клавиатуры. В стратегии №1 любой ключ может быть превращен в Enter, но не специально Numpad Enter. Со стратегией №2 Numpad Enter по-прежнему имеет тот же скан-код, что и обычно.

На аппаратном уровне Enter отправляет 0x1C пока Numpad Enter отправляет 0xE0 0x1C(источник: мои собственные наблюдения и документ Андриса Брауэра). В Windows есть разные способы сообщить об этом: с битом 24WM_KEYDOWNс lParam, то LLKHF_EXTENDEDфлаг для крючков клавиатуры низкого уровня,RI_KEY_E0 флаг для Raw Input и, возможно, больше.

Короче говоря, можно с уверенностью предположить, что Numpad Enter - это 0x1C плюс флаг расширенного ключа, поскольку в любом другом случае его невозможно идентифицировать.

Я знаю, что на моей клавиатуре это 0x9C (156)

Я предполагаю, что вы получили это значение от DirectInput, который определяет константу перечисленияDIK_NUMPADENTERсо значением 0x9C. Это значение не является скан-кодом.

Код сканирования зависит от оборудования, он может не совпадать в другой системе. Может быть несколько кодов сканирования, которые сопоставляются с виртуальным ключом. Виртуальные ключи должны быть несколько общими и не привязанными к оборудованию.

Вы можете сказать разницу в WM_KEYDOWN а также WM_KEYUP; WPARAM является VK_RETURN и бит 24 установлен в LPARAM когда используется клавиша Enter на цифровой клавиатуре:

Указывает, является ли клавиша расширенной клавишей, такой как клавиши ALT и CTRL справа, которые появляются на улучшенной клавиатуре с 101 или 102 клавишами. Значение равно 1, если это расширенный ключ; в противном случае это 0.

GetKeyboardType может рассказать вам некоторую информацию о "клавиатуре", но, поскольку в наши дни может быть подключено более одной клавиатуры, вам придется пойти глубже, чтобы узнать, есть ли какие-нибудь клавиатуры, которые имеют свойства, которые вы ищете. Возможно, SetupAPI знает.

Андерс делает хорошее замечание - я не знаю, как определить, присутствует ли эта клавиша на одной из клавиатур в какой-либо конкретной системе. Также не забывайте об экранной клавиатуре и сенсорных устройствах в целом.

Почему бы просто не связать свою функцию с обеими клавишами? У тебя есть веская причина не делать этого?

В дополнение к отличному ответу @Lexikos:

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

Это было верно в древние времена. По крайней мере, поскольку система Windows NT использует набор кодов сканирования PS/2 1 для всех API-интерфейсов клавиатуры. С некоторыми ошибками, которые специально поддерживаются для обратной совместимости (например коды сканирования NumLock и Pause меняются местами. Они специальные .).

Во всех операционных системах Microsoft все клавиатуры фактически передают значения Scan Code Set 2 по кабелю от клавиатуры к порту клавиатуры. Эти значения преобразуются в набор кодов сканирования 1 микросхемой порта i8042. Остальная часть операционной системы и все приложения, обрабатывающие коды сканирования, ожидают, что значения будут из набора кодов сканирования 1. Набор кодов сканирования 3 не используется и не требуется для работы операционных систем Microsoft. ( Спецификация кода сканирования клавиатуры, редакция 1.3a — 16 марта 2000 г. )

По этой причине в некоторых документах API скан-коды рассматриваются как виртуальные скан-коды.

Современные клавиатуры USB или Bluetooth используют протокол HID с идентификаторами использования HID для сообщения о нажатиях клавиш (см. 10 Keyboard/Keypad Page (0x07)в спецификации HID Usage Tables список возможных идентификаторов использования клавиш клавиатуры).

Эти использования HID преобразуются в набор кодов сканирования PS/2 1 с помощью драйвера kbdclass (драйвер преобразователя HID-клиента для клавиатур ) посредством вызова API HidP_TranslateUsagesToI8042ScanCodes . Он работает в соответствии с опубликованной спецификацией . Итак, у нас есть опубликованный список кодов сканирования, который используется в Windows. Если вам интересна история этого бардака со скан-кодом — есть хорошая страница .

Невозможно определить, присутствует ли кнопка Enter на определенной клавиатуре.

Другие вопросы по тегам