Delphirus - прграммирование на delphi
   Все о delphi Delphirus - прграммирование на delphi
blocks.gif
Навигация
 

Главная
Статьи
Базы данных
Графика
Защита
Интернет
Система
Тексты
Мультимедиа
Файлы
Формы и окна
Другое
Советы
Базы данных
Графика
Интернет
Мультимедиа
Система
Тексты
Файлы
Файлы
Исходники
Компоненты
Инфо
Поиск по сайту
Обратная связь
Самое популярное
Аккаунт
Карта сайта

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

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

 
Разместил 06/02/2004 от rolcom ( Прочитано: )

  blocks.gif
Связанные ссылки
 

· Больше про Работа с Windows и железом
· Новость от rolcom


Самая читаемая статья: Работа с Windows и железом:
Запуск приложений из Delphi

 
blocks.gif
Рейтинг статьи
 

Средняя оценка: 3.88
Ответов: 9


Пожалуйста, проголосуйте за эту статью:

Отлично
Очень хорошо
Хорошо
Нормально
Плохо


 
blocks.gif
опции
 


 Напечатать текущую страницу  Напечатать текущую страницу

 Отправить статью другу  Отправить статью другу

 
 

Page generation 0.082 seconds