Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Хуки


volser ©   (2004-08-03 17:55:00) 

Питаюсь перехватить сообщение дабл клик, но у меня ничего не получается. Что делаю не так? Вот код:

DLL:

type
 TMessageHookCallBack=procedure (Messag : CWPSTRUCT);

function SetMessageHook(Switch : Boolean; CallBack:TMessageHookCallBack):boolean export; stdcall;

implementation

var
 MessageHook: HHook;
 MH:TMessageHookCallBack;

function GetMsgProc(code : integer; wParam : wParam; lParam : lParam) : longint; stdcall;
begin
 if code=HC_ACTION then
 begin
    if PCWPStruct(Pointer(lParam))^.message=WM_LBUTTONDBLCLK then
      MH(PCWPStruct(Pointer(lParam))^);
 end;
 Result:= CallNextHookEx(MessageHook, Code, wParam, lParam);
end;

function SetMessageHook(Switch : Boolean; CallBack : TMessageHookCallBack):boolean export; stdcall;
begin
 if switch=true then
 begin
   MessageHook := SetWindowsHookEx(WH_CALLWNDPROC, @GetMsgProc, HInstance, 0);
   Result:=MessageHook<>0;
   MH:=CallBack;
 end
 else
 begin
   Result:=UnhookWindowsHookEx(MessageHook);
 end;
end;
end.


App:

...
function SetMessageHook(Switch : Boolean; CallBack : Pointer):boolean stdcall; external 'ControlHooks.dll';...

procedure MessageHookCallBack(Messag : CWPSTRUCT);
begin
 ShowMessage('b');
end;
...

в FormCreate

SetMessageHook(True, @MessageHookCallBack);
в FormClose

SetMessageHook(False, nil);

С таким кодом вообще ничего не происходит.
Если перехватывать WM_PAINT, то вроде работает


volser   (2004-08-05 19:34:00) [1]

Вот я и сделал все по этой статье, но у меня почему то не работает с хуком WH_CALLWNDPROC.


хук   (2004-08-05 19:11:00) [2]

http://www.delphimaster.ru/articles/hooks/index.html+ Архив с примерами к статье: example.zip


volser   (2004-08-05 18:28:00) [3]

Почитал статью и родил второй вариант, но он тоже почему то не работает:
DLL:


const
 MMFName: PChar = '_KeyMMF'; // имя объекта файлового отображения

 WM_APPKEYDOWN    =  WM_USER + 1;

type
 PGlobalDLLData = ^TGlobalDLLData;
 TGlobalDLLData = packed record
   SysHook: HWND;
   MyAppWnd: HWND;
 end;

var
 GlobalData: PGlobalDLLData;
 MMFHandle: THandle;

function WndProc(code : integer; wParam : word; lParam : longint) : longint; stdcall;
begin

 if code < 0 then
 begin
   Result:= CallNextHookEx(GlobalData^.SysHook, Code, wParam, lParam);
   Exit;
 end;

  Case PCWPStruct(Pointer(lParam))^.message of
    WM_KEYDOWN : begin
       PostMessage(GlobalData^.MyAppWnd, WM_APPKEYDOWN, wParam, lParam);
    end;
  end;

 CallNextHookEx(GlobalData^.SysHook, Code, wParam, lParam);
 Result:= 0;

end;

procedure hook(switch : Boolean; hMainProg: HWND) export; stdcall;
begin
 if switch=true then
 begin
   GlobalData^.SysHook := SetWindowsHookEx(WH_CALLWNDPROC, @WndProc, HInstance, 0);
   GlobalData^.MyAppWnd:= hMainProg;
 end else
 begin
   UnhookWindowsHookEx(GlobalData^.SysHook);
 end;
end;

procedure OpenGlobalData();
begin
 MMFHandle:= CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE, 0, SizeOf(TGlobalDLLData), MMFName);
 GlobalData:= MapViewOfFile(MMFHandle, FILE_MAP_ALL_ACCESS, 0, 0, SizeOf(TGlobalDLLData));
end;

procedure CloseGlobalData();
begin
 UnmapViewOfFile(GlobalData);
 CloseHandle(MMFHandle);
end;

procedure DLLEntryPoint(dwReason: DWord); stdcall;
begin
 case dwReason of
   DLL_PROCESS_ATTACH: OpenGlobalData;
   DLL_PROCESS_DETACH: CloseGlobalData;
 end;
end;

exports hook;

begin
 DLLProc:= @DLLEntryPoint;
 DLLEntryPoint(DLL_PROCESS_ATTACH);
end.


App:

procedure SetHook;
var
 Hook: procedure (switch : Boolean; hMainProg: HWND) stdcall;
begin
 @hook:= nil;
 hDLL:= LoadLibrary(PChar('hooks.dll'));
 if hDLL > HINSTANCE_ERROR then
 begin
   @hook:=GetProcAddress(Hdll, 'hook');
   hook(true, frmMain.Handle);
 end else
 begin
   ShowMessage('Ошибка при загрузке DLL !');
   Exit;
 end;
end;

procedure UnSetHook;
var
 Hook: procedure (switch : Boolean; hMainProg: HWND) stdcall;
begin
 @hook:= nil;
 hDLL:= LoadLibrary(PChar('hooks.dll'));
 if hDLL > HINSTANCE_ERROR then
   begin
     @hook:=GetProcAddress(Hdll, 'hook');
     hook(false, frmMain.Handle);
     if FreeLibrary(hDLL) then  sleep(1000);
   end
 else
 begin
   ShowMessage('Ошибка при загрузке DLL !');
   Exit;
 end;
end;

TfrmMain = class(TForm)
...
procedure AppKeyDown(var Message: TMessage); message WM_APPKEYDOWN;

...
procedure TfrmMain.AppKeyDown(var Message: TMessage);
begin
 Showmessage('cool');
end;



Но ничего не происходи. Где я туплю?


Digitman   (2004-08-05 09:09:00) [4]


> volser   (03.08.04 22:25) [2]


мало того, даже если MH сделать глобально-доступной (см. Юрий Зотов ©   (04.08.04 14:04) [6]), грубой ошибкой будет обращение по адресу, хранимому в этой переменной, с целью вызова процедуры, якобы находящейся по этому адресу .. только для процесса, устанавливающего ловушку, это будет работать безошибочно, для прочих же процессов это неминуемо приведет к AV


Юрий Зотов   (2004-08-04 14:04:00) [5]

> GrayFace ©   (04.08.04 11:34) [4]

> Еще одна ошибка в том, что не всегда надо делать
> Result:= CallNextHookEx(MessageHook, Code, wParam, lParam);

Можно не всегда, а можно и всегда. Это не ошибка.

> volser   (03.08.04 17:55)  

Переменная MessageHook должна быть глобальной на уровне всей системы. Например, можно хранить ее в страничной памяти Windows
(CreateFileMapping + MapViewOfFile). Прочтите статью Алексея Павлова на этом сайте.


Digitman   (2004-08-04 12:59:00) [6]


> GrayFace ©   (04.08.04 11:34) [4]


насчет того, что это ошибка - спорный момент

по соотв.инф-ции в MSDN этот вызов лишь настоятельно рекомендуетсявыполнять

цитата :

Calling CallNextHookEx is optional, but it is highly recommended; otherwise, other applications that have installed hooks will not receive hook notifications and may behave incorrectly as a result. You should call CallNextHookEx unless you absolutely need to prevent the notification from being seen by other applications.


GrayFace   (2004-08-04 11:34:00) [7]

Поиск: hooks
Еще одна ошибка в том, что не всегда надо делать Result:= CallNextHookEx(MessageHook, Code, wParam, lParam);


Digitman   (2004-08-04 08:30:00) [8]


> оно не посылалось, значит проблема не MH


замечательная причинно-следственная связь !

еще раз - это грубая ошибка, которая обязательно "выстрелит",


volser   (2004-08-03 22:25:00) [9]

Все равно не понял что мне нужно поменять.
Для хука WH_MOUSE_LL я писал аналогичный код и он работал.

Вместо вызова функци MH(PCWPStruct(Pointer(lParam))^);
я пробовал посылать сообщение в мое приложение, но оно не посылалось, значит проблема не MH.


Digitman   (2004-08-03 18:10:00) [10]


> MH:TMessageHookCallBack


грубая ошибка
эта переменная д.б. глобально доступной для всех экз-ров хук-модулей


Наверх

Титульная страница Поиск, карта сайта Написать письмо