Обработка сообщений клавиатуры

Статьи » Система » Обработка сообщений клавиатуры

 Существует несколько способов обработки сообщений от клавиатуры, каждый метод пригоден для той или иной ситуации. Рассмотрим самые основные и распространенные методы обработки сообщений клавиатуры.

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/

Immortal_Death ©

Источник www.delphi.hostmos.ru

Другое по теме:

Категории

Статьи

Советы

Copyright © 2022 - All Rights Reserved - www.delphirus.com