![]() |
|
|
|||||||
| Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
|
Опции темы | Поиск в этой теме | Опции просмотра |
|
|
|
#1
|
|||
|
|||
|
С ловушками никогда серъезного дела не имел, сначала прочитал статью: http://www.delphisources.ru/pages/fa.../set_hook.html
Из нее я понял, что на hook реагирует функция, находящаяся в библиотеке DLL, там же происходит и обработка перехваченного сообщения. А скажите, как сделать так, чтобы обработка этих сообщений происходила в EXE, т.е. динамическая библиотека будет только их перехватывать и возвращать для обработки в exe, потому что основная программа находится там? |
|
#2
|
||||
|
||||
|
вариантов много. один из них: при установке хука в библиотеку передается handle окна, которое создано в exe. хоть главной формы, если есть, хоть AllocateHWnd, если ее нет. в библиотеке через CreateFileMapping-MapViewOfFile сохраняем этот handle. просто сохранить его в глобальной переменной нельзя!!! ну и потом при срабатывании хука посылаем окну соотв. сообщение.
|
|
#3
|
|||
|
|||
|
То есть, в экспортируемою из библиотеке функцию, которая устанавливает ловушку, передается Handle главного окна, там создается CreateFileMapping и MapViewOfFile и в него записывается Handle как 4-байтовая переменная. Но как я понял, адрес, который возвращает MapViewOfFile в обработчике ловушки использовать нельзя? Нужно опять использовать CreateFileMapping, используя имя файла (параметр lpName: PChar), правильно?
|
|
#4
|
||||
|
||||
|
простейший пример:
Код:
library Hook;
uses Windows, Messages;
type
PGlobalData = ^TGlobalData;
TGlobalData = record
TargetWnd: HWND;
MessageWnd: Cardinal;
end;
const
FileMappingName: PChar = 'Creates_or_opens_a_named_or_unnamed_file_mapping_object';
var
FileMappingHandle: THandle;
GlobalData: PGlobalData = nil;
hCallWndProc: HHOOK = 0;
function CallWndProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
if nCode=HC_ACTION then
PostMessage(GlobalData^.TargetWnd, GlobalData^.MessageWnd, wParam, lParam);
Result:=CallNextHookEx(0, nCode, wParam, lParam);
end;
procedure SetHook(ATargetWnd: HWND; AMessageWnd: Cardinal);
begin
GlobalData^.TargetWnd:=ATargetWnd;
GlobalData^.MessageWnd:=AMessageWnd;
hCallWndProc:=SetWindowsHookEx(WH_CALLWNDPROC, @CallWndProc, HInstance, 0);
end;
procedure UnSetHook();
begin
UnhookWindowsHookEx(hCallWndProc);
GlobalData^.MessageWnd:=0;
GlobalData^.TargetWnd:=0;
end;
exports SetHook, UnSetHook;
procedure DLLHandler(Reason: Integer);
begin
case Reason of
DLL_PROCESS_ATTACH: begin
FileMappingHandle:=CreateFileMapping($ffffffff, nil, PAGE_READWRITE, 0, SizeOf(TGlobalData), FileMappingName);
GlobalData:=MapViewOfFile(FileMappingHandle, FILE_MAP_ALL_ACCESS, 0, 0, SizeOf(TGlobalData));
end;
DLL_PROCESS_DETACH: begin
UnmapViewOfFile(GlobalData);
CloseHandle(FileMappingHandle);
end;
end;
end;
begin
DllProc:=@DLLHandler;
DLLHandler(DLL_PROCESS_ATTACH);
end. |
|
#5
|
|||
|
|||
|
Отлично, вроде все работает. Суть в том, что в основную программу надо передать код нажатой клавиши. Ловушку я поставил на WH_GETMESSAGE и функцию перехвата сделал такой:
Код:
function CallWndProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
var
Msg: TMsg;
begin
if nCode= HC_ACTION then
begin
Msg:= TMsg(Pointer(LParam)^);
if Msg.message = WM_KEYDOWN then
PostMessage(GlobalData^.TargetWnd, GlobalData^.MessageWnd, Msg.wParam, lParam);
end;
Result:=CallNextHookEx(0, nCode, wParam, lParam);
end;В основной программе (EXE) такой код: Код:
const
CM_HOOK = WM_USER + 1;
type
TForm1 = class(TForm)
....
private
{ Private declarations }
procedure CMHook(var Msg: TMessage); message CM_HOOK;
public
end;
procedure TForm1.CMHook(var Msg: TMessage);
begin
{Обрабатываем нажатие клавиши с кодом Msg.WParam}
end;
//Установка ловушки:
SetHook(Handle, CM_HOOK);
Я правильно поступил? |