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