Делфи реализует в объектах элементов интерфейса различные события — в том числе нажатия клавиш. Но мы получаем уже конкретные ASCII коды, при этом приложение должно удерживать фокус ввода. Как же работать с состоянием клавиатуры без событий onkey и получить информацию о статусах клавиш даже ни имея фокуса ввода?
Для чего это может понадобиться? Приложения читающие клавиатуру, не имея фокуса ввода, вообще то довольно подозрительны. Они вызывают соответствующую реакцию у эвристических алгоритмов антивирусных программ.
Читать клавиатуру без фокуса ввода нужно, наример, такому приложению как известный многим punto switcher.
А я когда давно писал программу UO shra’s pilot, для программирования и запуска макросов в Ultima Online. Там мне приходилось закреплять окошко пульта управления «пилотом» поверх всех окон, т.к. для запуска скрипта нужно было нажать соответствующую кнопку на панели. Сейчас бы я сделал иначе, например, закрепил вызов скриптов за функциональными клавишами или их комбинациями.
Рассмотрим основные функции, которые нам предоставляют библиотеки ОС.
Вот интересные функции, входящие в состав USER32.dll. В Delphi они объявляются в юните windows.
Две функции читают состояние определенной клавиши, а третья — считывает состояние сразу всей клавиатуры в указанный буфер памяти (256 байт).
function GetKeyState(virtKey: Integer);
function GetAsyncKeyState(key: Integer);
function GetKeyboardState(var: KeyState: Byte);
Так как функции возвращают «какие то» состояния, возникает вопрос как с ними работать.
Как проверить нажата или нет виртуальная кнопка?
Вот так можно проверить нажата или нет клавиша «левый шифт»:
1 2 3 4 5 |
var pressed: boolean; begin pressed := getasynckeystate(VK_LSHIFT)<>0; ... end; |
Чем отличается GetKeyState() от GetAsyncKeyState()?
Суть их работы примерно одинакова. Но есть кое какие отличия. Битовая маска состояния клавиш на выходе этих функций отличается. Подробности описывать не стану, т.к. выше есть ссылка на помощь microsoft. Покажу лучше пару примеров, чтобы вам меньше забивать себе голову всякой всячиной :).
Одна функция проверяет зажат ли шифт (любой из двух), а вторая проверяет статус CAPSLOCK.
1 2 3 4 5 6 7 8 |
function ShiftKeyDown : boolean; begin result:= GetKeyState(VK_SHIFT) and $80 = $80; end; function GetCapsLockStatus : boolean; begin result:=(GetKeyState(VK_CAPITAL) and 1) = 1; end; |
Что может нам ещё понадобиться при чтении данных с клавиатуры? Возможно, стоит проверить текущую раскладку активного приложения.