HotKey

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

HotKey

Сообщение ADR » 11.05.2010 18:31:16

Нужно чтобы программа получала сообщения при нажиманни alt и если нажать alt то от клавиш num если num включен
как так сделать? (Прога должна сидеть в трее и лапать сообщение)
ADR
новенький
 
Сообщения: 43
Зарегистрирован: 11.05.2010 18:22:39
Откуда: Ukraine

Re: HotKey

Сообщение Maxizar » 13.05.2010 13:06:44

Что такое НООК?

НООК - это механизм перехвата сообщений, предоставляемый системой Microsoft Windows. Программист пишет специального вида функцию (НООК-функция), которая затем при помощи функции SetWindowsHookEx вставляется на верх стека НООК-функций системы. Ваша НООК-функция сама решает, передать ли ей сообщение в следующую НООК-функцию при помощи CallNextHookEx или нет.

Какие бывает НООК'и?

НООК бывают глобальные, контролирующие всю систему, так и локальные, ориентированные на какой-либо поток (Thread). Кроме того НООК различаются по типу перехватываемых сообщений (подробнее об этом - ниже). НООК несколько подтормаживают систему, поэтому ставить их рекомендуется только при необходимости, и кактолько необходимость в них отпадает - удалять.

Как создавать НООК?

НООК устанавливается в систему при помощи функции SetWindowsHookEx, вот её заголовок:
function SetWindowsHookEx(idHook: Integer; lpfn: TFNHookProc;
hmod: HINST; dwThreadId: DWORD): HHOOK;


idHook
константа, определяющая тип вставляемого НООК'а, должна быть одна из нижеследующих констант:
WH_CALLWNDPROC
вставляемая НООК-функция следит за всеми сообщения перед их отпралением в соответствующую оконную функцию
WH_CALLWNDPROCRET
вставляемая НООК-функция следит за всеми сообщениями после их отправления в оконную функцию
WH_CBT
вставляемая НООК-функция следит за окнами, а именно: за созданием, активацией, уничтожением, сменой размера; перед завершением системной команды меню, перед извлечением события мыши или клавиатуры из очереди сообщений, перед установкой фокуса и т.д.
WH_DEBUG
вставляемая НООК-функция следит за другими НООК-функциями.
WH_GETMESSAGE
вставляемая НООК-функция следит за сообщениями, посылаемыми в очередь сообщений.
WH_JOURNALPLAYBACK
вставляемая НООК-функция посылает сообщения, записанные до этого WH_JOURNALRECORD НООК'ом.
WH_JOURNALRECORD
эта НООК-функция записывает все сообщения куда-либо в специальном формате, причем позже они могут быть "воспроизведены" при помощи НООК'а WH_JOURNALPLAYBACK. Это в некотором роде аналог магнитофонной записи сообщений.
WH_KEYBOARD
вставляемая НООК-функция следит за сообщениями клавиатуры
WH_MOUSE
вставляемая НООК-функция следит за сообщениями мыши
WH_MSGFILTER
WH_SHELL
WH_SYSMSGFILTER

lpfn
указатель на непосредственно функцию. Обратите внимание, что если Вы ставите глобальный НООК, то НООК-функция обязательно должна находиться в некоторой DLL!!!
hmod
описатель DLL, в которой находится код функции.
dwThreadId
идентификатор потока, в который вставляется НООК

Подробнее о НООК-функциях сотри справку по Win32API МСДН корче.

Как удалять НООК?

НООК удаляется при помощи функции UnHookWindowsEx.

Пример использования НООК.
Я реализовал программу с глобальным хуком, которая ловит нажатие клавиши А(Буржуйской) и бибикает при каждом отлове, и записывает число нажатий в ини файл см исходник. Реализация ясное дело кривая НО для примера самя То.
Вот код DLL:
Код: Выделить всё
library Hook;

{$mode objfpc}{$H+}

uses
  windows, messages, IniFiles
  { you can add units after this };
  //модуль Classes удален для экономии размера ДЛЛ


var
    theHook: THandle;  //хэндл ловушки для дальнейшего удаления


function MouseHook(nCode, wParam, lParam: integer): Lresult; stdcall;
var Ini:TIniFile;
     X:Integer;
begin

   if nCode < 0 then
  begin            //фигня какая то, передаем дальше
    result := CallNextHookEx(theHook, nCode, wParam, lParam);
    exit;
  end;
           //(lParam >$8000) - считаем только нажатие клавиш (GetKeyState(VK_SHIFT)<>0)
    if (wParam = VK_A) and (lParam >$8000)     then
     begin
     Ini:=TIniFile.Create('C:\Count.Ini');
     X:=Ini.ReadInteger('Count','Value',0);
     Ini.WriteInteger('Count','Value',X+1); //тупо  подсчет числа нажатий данной клавиши
     Ini.Free;
     beep(100,100);  //Ну для красоты чтоб слышать что идет отлов
     end;

    result := CallNextHookEx(theHook, nCode, wParam, lParam); //дальше по цепочке
end;

//-------------------------------------------------------------------------
procedure Start;
begin
  theHook := SetWindowsHookEx(WH_KEYBOARD, @MouseHook, hInstance, 0); //установка ловушки
  if theHook = 0 then
    messageBox(0, 'Error!', 'Error!', mb_ok);
end;
//-------------------------------------------------------------------------
procedure Remove;
begin
  UnhookWindowsHookEx(theHook);   //удаление ловушки
end;
//-------------------------------------------------------------------------
{$R *.res}

Exports

Start     index 1 name 'Start',
Remove    index 2 name 'Remove';

begin
end.



Вот код формы, которая и запускает при старте это хук. Так как хук глобальный то можно прогу вообще скрыть и тп, и будем ловить нажатие хоть в Ворде. Коды клавишь см в исходниках. Что касается Дополнительных параметров см МСДН про пораметр lParam ну или функция GetKeyState(VK_SHIFT)<>0 - в данном случае даст труе если нажат Шифт.

Код: Выделить всё
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
  StdCtrls, ExtCtrls,Windows;

type

  { TForm1 }

  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;


var
  Form1: TForm1;

  //экспортируем 3 функции из библиотеки с НООК'ами
  procedure Start; external 'Hook.dll' name 'Start';
  procedure Remove; external 'Hook.dll' name 'Remove';

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
    Start; //Старт ловушки
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
   Remove;   //Ой убивают Хэлп ми
end;


end.




Надеюсь я вам помог, Но есть одно НО - я всегда не прав и вы не должны меня слушать.
Maxizar
постоялец
 
Сообщения: 385
Зарегистрирован: 20.03.2010 19:48:14

Re: HotKey

Сообщение ADR » 13.05.2010 16:30:17

спасибо но мне надо в обход модуля Windows так как он отсутствует в Лазарус под линукс ...

Добавлено спустя 2 минуты 31 секунду:
и почему в этом коде выдает ошибку
Код: Выделить всё
unit1.pas(32,1) Fatal: Selected assembler reader not supported
Код: Выделить всё
procedure AAA(var xah, xal:byte);
begin
asm
mov ah,10h {функция чтения из клавиатуры}
int 16h
mov xah, ah
mov xal, al
end;
writeln('Symbol = ', xal, ' Scan = ', xah);
end.
ADR
новенький
 
Сообщения: 43
Зарегистрирован: 11.05.2010 18:22:39
Откуда: Ukraine

Re: HotKey

Сообщение FeodoR » 14.05.2010 11:39:11

Надо задать нужный интерпретатор ассемблера директивой {$ASMMODE}. В данном случае - {$ASMMODE INTEL}
Аватара пользователя
FeodoR
новенький
 
Сообщения: 59
Зарегистрирован: 16.04.2010 12:11:34
Откуда: MSK, ЮАО

Re: HotKey

Сообщение PapaNT » 07.08.2013 17:25:10

Пример замечательный, но перехват клавиатуры работает только в окне программы вызывающей dll
PapaNT
постоялец
 
Сообщения: 167
Зарегистрирован: 11.09.2009 12:06:46
Откуда: Москва

Re: HotKey

Сообщение OberonAR » 09.12.2015 13:10:55

PapaNT писал(а):Пример замечательный, но перехват клавиатуры работает только в окне программы вызывающей dll


Так все таки это глобальный хук или в пределах вызывающей программы?
Кто нибудь проверял?
Мне вот необходимо разобраться с глобальным, чтобы из любого места системы (любой программы) реагировать на сочетание клавиш.
Аватара пользователя
OberonAR
новенький
 
Сообщения: 73
Зарегистрирован: 08.02.2012 11:46:04
Откуда: Краснодарский край

Re: HotKey

Сообщение PapaNT » 09.12.2015 16:47:20

В Win >=7 без ЭЦП подобное не катит.
PapaNT
постоялец
 
Сообщения: 167
Зарегистрирован: 11.09.2009 12:06:46
Откуда: Москва

Re: HotKey

Сообщение OberonAR » 09.12.2015 16:59:11

PapaNT писал(а):В Win >=7 без ЭЦП подобное не катит.


Вы имеете ввиду, что мою программу необходимо подписывать и соответствующий сертификат прописывать в систему?
Если да - есть ли другие пути?
Аватара пользователя
OberonAR
новенький
 
Сообщения: 73
Зарегистрирован: 08.02.2012 11:46:04
Откуда: Краснодарский край

Re: HotKey

Сообщение PapaNT » 09.12.2015 17:04:04

У меня дело закончилось расстрельной статьей от безопасности...
PapaNT
постоялец
 
Сообщения: 167
Зарегистрирован: 11.09.2009 12:06:46
Откуда: Москва

Re: HotKey

Сообщение OberonAR » 09.12.2015 17:35:59

В общем - работает пример. Даже на нажатие из других программ реагирует
Аватара пользователя
OberonAR
новенький
 
Сообщения: 73
Зарегистрирован: 08.02.2012 11:46:04
Откуда: Краснодарский край

Re: HotKey

Сообщение PapaNT » 09.12.2015 17:43:23

С самоподписным сертификатом?
PapaNT
постоялец
 
Сообщения: 167
Зарегистрирован: 11.09.2009 12:06:46
Откуда: Москва

Re: HotKey

Сообщение OberonAR » 10.12.2015 17:32:55

Вообще без сертификатов. Как в примере. Win7 32.
Аватара пользователя
OberonAR
новенький
 
Сообщения: 73
Зарегистрирован: 08.02.2012 11:46:04
Откуда: Краснодарский край

Re: HotKey

Сообщение PapaNT » 16.12.2015 03:38:14

Я пытался сделать глобальный хук и проверял его работу в другом приложении.
PapaNT
постоялец
 
Сообщения: 167
Зарегистрирован: 11.09.2009 12:06:46
Откуда: Москва


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 222

Рейтинг@Mail.ru