Использование НООК в Delphi

Что такое НООК?
НООК - это механизм перехвата сообщений, предоставляемый системой 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.

Пример использования НООК.
Ставим НООК, следящий за мышью (WH_MOUSE). Программа следит за нажатием средней кнопки мыши, и когда она нажимается, делает окно, находящееся непосредственно под указателем, поверх всех остальных (TopMost). Код самой НООК-функции помещен в библиотеку lib2.dll, туда же помещены и функции Start - для установки НООК, и Remove - для удаления НООК.

Файл sticker.dpr

program sticker;  
  
uses windows, messages;  
  
  
var   wc : TWndClassEx;  
 MainWnd : THandle;  
    Mesg : TMsg;  
//экспортируем две функции из библиотеки с НООК'ами  
procedure Start; external 'lib2.dll' name 'Start';  
procedure Remove; external 'lib2.dll' name 'Remove';  
  
function WindowProc(wnd:HWND; Msg : Integer; Wparam:Wparam; Lparam:Lparam):Lresult; stdcall;  
var nCode, ctrlID : word;  
Begin  
case msg of  
wm_destroy :  
  Begin  
   Remove;//удаляем НООК  
   postquitmessage(0); exit;  
   Result:=0;  
  End;  
  
  else Result:=DefWindowProc(wnd,msg,wparam,lparam);  
end;  
End;  
  
  
begin  
  
wc.cbSize:=sizeof(wc);  
wc.style:=cs_hredraw or cs_vredraw;  
wc.lpfnWndProc:=@WindowProc;  
wc.cbClsExtra:=0;  
wc.cbWndExtra:=0;  
wc.hInstance:=HInstance;  
wc.hIcon:=LoadIcon(0,idi_application);  
wc.hCursor:=LoadCursor(0,idc_arrow);  
wc.hbrBackground:=COLOR_BTNFACE+1;  
wc.lpszMenuName:=nil;  
wc.lpszClassName:='WndClass1';  
  
RegisterClassEx(wc);  
  
  
MainWnd:=CreateWindowEx(0,'WndClass1',  
'Caption',  
ws_overlappedwindow,  
cw_usedefault,cw_usedefault,cw_usedefault,cw_usedefault,0,0,  
Hinstance,nil);  
  
  
ShowWindow(MainWnd,CmdShow);  
  
Start;//вставляем НООК  
  
While GetMessage(Mesg,0,0,0) do  
 begin  
  TranslateMessage(Mesg);  
  DispatchMessage(Mesg);  
 end;  
  
end.  

Файл lib2.dpr

library lib2;  
  
  
uses  
  windows, messages;  
var  
  pt : TPoint;  
  theHook : THandle;  
  
function MouseHook(nCode, wParam, lParam : integer) : Lresult; stdcall;  
var  
  msg : PMouseHookStruct;  
  w : THandle;  
  style : integer;  
  
Begin  
  if nCode<0 then begin  
    result := CallNextHookEx(theHook, nCode, wParam, lParam);  
    exit;  
  end;  
  msg := PMouseHookStruct(lParam);  
  
  case wParam of  
    WM_MBUTTONDOWN : pt := msg^.pt;  
    WM_MBUTTONUP : begin  
      w := WindowFromPoint(pt);  
      style := GetWindowLong(w, GWL_EXSTYLE);  
      if (style and WS_EX_TOPMOST) <> 0 then begin  
        //уже поверх всех - сделать обычным  
        ShowWindow(w, sw_hide);  
        SetWindowPos(w, HWND_NOTOPMOST, 0,0,0,0, SWP_NOMOVE or SWP_NOSIZE  OR SWP_SHOWWINDOW);  
      end  
      else begin  
        //сделать поверх остальных   
        ShowWindow(w, sw_hide);  
        SetWindowPos(w, HWND_TOPMOST, 0,0,0,0, SWP_NOMOVE OR SWP_NOSIZE OR SWP_SHOWWINDOW);  
      end;  
  
    end;  
  end;  
  
  
  result := CallNextHookEx(theHook, nCode, wParam, lParam);  
End;  
  
  
procedure Start;  
begin  
  
  theHook := SetWindowsHookEx(wh_mouse, @mouseHook, hInstance, 0);  
  if theHook = 0 then messageBox(0,'Error!','Error!',mb_ok);  
end;  
  
procedure Remove;  
begin  
  UnhookWindowsHookEx(theHook);  
end;  
  
  
  
exports  
Start index 1  name 'Start',  
Remove index 2 name 'Remove';  
  
  
end. 

Всё.

Автор: Sergey Stolyarov
Теги:
НООК
Добавлено: 31 Июля 2018 07:33:39 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...