Delphi - объектно-ориентированный язык программирования, разработанный компанией Borland в 1995 году. Он основан на языке программирования Pascal, но имеет более расширенные возможности и добавлены новые функции.
Delphi является интегрированной средой разработки (IDE), которая позволяет разрабатывать программное обеспечение для различных платформ, включая Windows, macOS, Android и iOS. Delphi достигает многоплатформенности с помощью...
Существует несколько способов обработки сообщений от клавиатуры, каждый метод пригоден для той или иной ситуации. Рассмотрим самые основные и распространенные методы обработки сообщений клавиатуры.
1. Обработка сообщений клавиатуры, посылаемых вашему приложению. Применяется когда, нужно обрабатывать сообщения клавиатуры и фокус ввода у вашего приложения. Есть несколько способов, рассмотрим два из них. Первый способ реализуется довольно просто: у формы устанавливаем свойство KeyPreview в True и обрабатываем событие OnKeyPress. К примеру, так: procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char); begin if Key = '1' then beep; //если нажата клавиша 1 выдать звук в системный динамик end; Примечание: не всегда звук будет выдаваться в системный динамик, иногда он выдается в колонки. Второй вариант, перехват события OnMessage объекта Application:Для начала создадим и пропишем свой обработчик перехватываемых событий: private //процедура для перехвата событий OnMessage обьекта Application procedure AppMessage(var Msg: TMsg; var Handled: Boolean); … procedure TForm1.AppMessage(var Msg: TMsg; var Handled: Boolean); begin … end; При запуске приложения (событие формы OnCreate) передаем обработку события OnMessage, нашей процедуре: procedure TForm1.FormCreate(Sender: TObject); begin Application.OnMessage := AppMessage; end; Теперь при возникновении любого события OnMessage, мы сможем его перехватить и обработать в процедуре AppMessage: AppMessage( var Msg: TMsg; //посылаемое сообщение var Handled: Boolean //определяет будет ли событие доходить до компонента //если Handled = True событие до компонента не дойдет ); Примечание: под фразами «дойдет/не дайдет до компонента» подразумевается, то, что когда Windows посылает сообщение нашей программе, его должен принять тот компонент, у которого в данный момент фокус ввода. Если мы поставим Handled = True, то компонент, которому предназначалось это событие, его не получит. Остается лишь написать обработчик: procedure TForm1.AppMessage(var Msg: TMsg; var Handled: Boolean); begin if Msg.message = WM_KEYDOWN //если нажата кнопка (кнопка удерживается), то then begin memo1.Lines.Add(Char(msg.wParam)); //добавляем в memo нажатую клавишу Handled := False; //сообщение дальше этого обработчика ПОЙДЕТ end; end; WM_KEYDOWN – событие возникает в момент нажатия и удержания кнопки. Так же можно применить: WM_KEYUP - событие возникает в момент отпускания кнопки, WM_KEYFIRST и др. 2. Регистрация в системе «горячих» клавиш (HotKey). Применяется тогда, когда нужно реагировать на нажатие, какой-либо клавиши (комбинации клавиш), в не зависимости от того у какого приложения в данный момент фокус ввода. Этот способ применяют для небольшого кол-ва клавиш, на которые должно реагировать ваше приложение. Для реализации этого метода в системе регистрируется «горячая» клавиша, после чего система будет посылать сообщение приложению, каждый раз, как будет нажата зарегистрированная клавиша. Регистрация клавиши происходит функцией RegisterHotKey Function RegisterHotKey( hWnd: HWND; // окно, которому посылается сообщение с «горячей» клавишей id: Integer; // идентификатор "горячей" клавиши fsModifiers, // флажки модификации клавиш vk: UINT // код виртуальной клавиши ): BOOL; fsModifiers может быть комбинацией следующих значений: MOD_ALT - Любая клавиша ALT должна удерживаться нажатой. MOD_CONTROL - Любая клавиша CTRL должна удерживаться нажатой. MOD_SHIFT - Любая клавиша SHIFT должна удерживаться нажатой MOD_WIN - Любая клавиша WINDOWS удерживалась нажатой. Примечание: в параметре fsModifiers, приведенные выше клавиши можно комбинировать обыкновенным сложением либо оператором OR. К примеру: MOD_ALT or MOD_CONTROL или MOD_ALT + MOD_CONTROL. Освобождение «горячей» клавиши выполняется функцией UnregisterHotKey function UnregisterHotKey( hWnd: HWND; // окно, которому посылается сообщение с «горячей» клавишей id: Integer // идентификатор "горячей" клавиши ): BOOL; посылаемое сообщение программе при нажатии «горячей» клавиши: WM_HOTKEY TWMHotKey = packed record Msg: Cardinal; HotKey: Longint; // код виртуальной клавиши Unused: Longint; // в младшем бите содержаться флажки модификаторы клавиш // (описаны выше: параметр fsModifiers функции RegisterHotKey) //в старшем бите содержится код виртуальной клавиши Result: Longint; //возвращает ноль в случае успеха end; Рассмотрим это на примере.
Создадим новый проект и поместим на форму memo, после чего надо создать и прописать принимаемое нами сообщение: private procedure WMHotKey(var Msg: TWMHotKey); message WM_HOTKEY; … procedure TForm1.WMHotKey(var Msg: TWMHotKey); begin … end; Создадим «горячую клавишу» объявив ее в глобальных константах: const HotKey1 = ord('R'); Зарегистрируем, «горячие» клавиши при открытии приложения (событие формы OnCreate) и снимем регистрацию при закрытии приложения (событие формы OnClose): procedure TForm1.FormCreate(Sender: TObject); begin RegisterHotKey(Form1.Handle, HotKey1, 0, HotKey1); end; procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin UnRegisterHotKey(Form1.Handle, HotKey1); end; Напишем обработчик принимаемого сообщения: procedure TForm1.WMHotKey(var Msg: TWMHotKey); //обработка сообщения var //посылаемого Windows s: String; begin case word(msg.Unused) of //определяем сочетания клавиш 0: S :='NOT'; //заданных в параметре fuModifiers 1: S :='MOD_ALT'; //функции RegisterHotKey 2: S :='MOD_CONTROL'; 3: S :='MOD_ALT + MOD_CONTROL'; 4: S :='MOD_SHIFT'; 5: S :='MOD_ALT + MOD_SHIFT'; 6: S :='MOD_CONTROL + MOD_SHIFT'; 7: S :='MOD_ALT + MOD_CONTROL + MOD_SHIFT'; 8: S :='MOD_WIN'; 9: S :='MOD_ALT + MOD_WIN'; 10: S :='MOD_CONTROL + MOD_WIN'; 11: S :='MOD_ALT + MOD_CONTROL + MOD_WIN'; 12: S :='MOD_SHIFT + MOD_WIN'; 13: S :='MOD_ALT + MOD_SHIFT + MOD_WIN'; 14: S :='MOD_CONTROL + MOD_WIN + MOD_SHIFT'; 15: S :='MOD_ALT + MOD_CONTROL + MOD_SHIFT+MOD_WIN'; else s := 'Сочетание неизвестно'; end; memo1.Lines.Add('Нажата зарегистрированная клавиша: '+ Char(msg.HotKey)+ ' сочетание fuModifiers: '+S); end; При нажатии на зарегистрированные клавиши, их буквенных представления, и сочетания заданные в параметре fsModifiers функции RegisterHotKey, будут выводиться в memo. 3. Определение нажатых клавиш в данный момент. Иногда возникает потребность, при каком-либо действии, проверить нажата ли та, или иная клавиша на клавиатуре, либо необходимо проверить включены ли, выключены ли, клавиши переключатели, такие как: Caps Lock, Num Lock и т.д. Пользоваться HotKey, в таком случае не удобно, да и не целесообразно. Использовать обработку сообщений клавиатуры, предназначенных только для нашего приложения, порой не просто не удобно, но и не имеет смысла, к примеру, не возможно будет узнать нажата ли клавиша, если фокус ввода не у нашего приложения. Для этих целей в Windows предусмотрены такие API функции, таких как: GetKeyState, GetAsyncKeyState, которые мы сейчас и рассмотрим. функция GetKeyState позволяет определить нажата ли та или иная клавиша в данный момент времени и включена или выключена клавиша переключатель в данный момент времени: function GetKeyState( nVirtKey: Integer //код виртуальной клавиши (ASCII таблица) ): SHORT; Если функция завершается успешно, величина возвращаемого значения определяет состояние данной виртуальной клавиши. Если старший бит равен 1, клавиша нажата; иначе она отпущена. Если младший бит равен 1, клавиша переключилась. Клавиша, такая как CAPS LOCK, переключается, если она является включенной. Клавиша выключена и не переключает, если младший бит равен 0. Когда клавиша переключается, индикатор переключения клавиши на клавиатуре (если он есть) должен быть включен, и отключен, когда клавиша не переключается. Поместим на форму Memo с кнопкой, и напишем обработчик события OnClick кнопки: procedure TForm1.Button1Click(Sender: TObject); var b: boolean; begin //для того, что бы узнать нажата ли в данный момент //та или иная клавиша, нам надо посмотреть старший бит //в возвращаемом значении функции GetKeyState b := (Word(GetKeyState(vk_Control)) shr 8)>0; //выводит 1 если клавиша CTRL нажата в данный момент и 0 //если отпущена memo1.Lines.Add('vk_Control: '+IntToStr(ord(b))); //если надо получить информацию о клавишах переключателях //таких как Caps LOCK, мы должны посмотреть младший бит //в возвращаемом значении функции GetKeyState b := (Word(GetKeyState(vk_Capital)))>0; //выводит 1 если клавиша Caps Lock включена в данный момент //и 0 если выключена memo1.Lines.Add('vk_Capital: '+IntToStr(ord(b))); end; Теперь рассмотрим функцию GetAsyncKeyState. Функция возвращает, была ли, клавиша нажата начиная с последнего вызова GetAsyncKeyState, и какое из двух состояний, нажатое или отпущенное, занимает в настоящее время клавиша. function GetAsyncKeyState( vKey: Integer // код виртуальной клавиши ): SHORT; Если старший значащий бит установлен, клавиша - нажата, если наименьший значащий бит установлен, клавиша была нажата после предыдущего вызова GetAsyncKeyState. Величина возвращаемого значения нулевая, если окно в другом потоке или процессе в настоящее время имеет фокус клавиатуры. Поместим на форму еще одну кнопку и напишем к ней обработчик: procedure TForm1.Button2Click(Sender: TObject); begin //выводит 1 если клавиша "2" была нажата с последнего момента вызова функции //и 0 если клавиша с последнего момента функции нажата НЕ была memo1.Lines.Add('Была нажата: '+ intToStr(ord((word(GetAsyncKeyState(50)))>0))); //выводит 1 если клавиша "2" нажата в данный момент и 0 если клавиша отпущена memo1.Lines.Add('Нажата сейчас: '+ intToStr(ord((word(GetAsyncKeyState(50) shr 8))>0))); end; 4. Глобальное слежение за всей клавиатурой. То есть слежение в не зависимости того, у какого приложения в данный момент фокус ввода. Реализуется с помощью специального механизма Windows – Hook. Hook – это ловушки, предназначенные для перехвата каких-либо событий, предназначенных для какого-либо приложения, до того, как эти события дойдут до этого приложения. Hook предназначен не только, для перехвата клавиатурных сообщений, но и для перехвата оных то же. Такое может потребоваться, к примеру, автопереключателям раскладки клавиатуры. Подробно останавливаться здесь не будем, эта тема хорошо разобрана, в Интернете, статей много. К примеру: http://www.delphimaster.ru/articles/hooks/index.html Архив с примерами к статье: KeyMsgs.zip Подробнее обо всех функциях вы можете прочитать в SDK, MSDN и т.п. Список использованной литературы: 1. http://www.firststeps.ru/2. http://msdn.microsoft.com/
Источник www.delphi.hostmos.ru