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