Delphi全局勾子和局部勾子

来源:岁月联盟 编辑:exp 时间:2012-06-02
1.安装勾子用SetWindowsHookEx function来实现,对于这个函数先来看MSDN解释
Installs an application-defined hook procedure into a hook chain. You would install a hook procedure to monitor the system for certain types of events. These events are associated either with a specific thread or with all threads in the same desktop as the calling thread. 参考MSDN
1 HHOOK WINAPI SetWindowsHookEx(
2 __in int idHook,//勾子类型
3 __in HOOKPROC lpfn,//回调函数的地址
4 __in HINSTANCE hMod,//一般为HInstance
5 __in DWORD dwThreadId,//关联进程的句柄,如果0则关联所有正在运行的进程,全局勾子时为0
6 );
勾子类型为下面的值

 


2.定义勾子的回调函数(hook procedure),回调函数CallWndProc callback function的定义如下
An application-defined or library-defined callback function used with the SetWindowsHookEx function. The system calls this function before calling the window procedure to process a message sent to the thread
1 LRESULT CALLBACK CallWndProc(
2   __in  int nCode,
3   __in  WPARAM wParam,
4   __in  LPARAM lParam
5 );
Parameters
nCode [in]
Type: int
Specifies whether the hook procedure must process the message. If nCode is HC_ACTION, the hook procedure must process the message. If nCode is less than zero, the hook procedure must pass the message to the CallNextHookEx function without further processing and must return the value returned by CallNextHookEx.
wParam [in]
Type: WPARAM
Specifies whether the message was sent by the current thread. If the message was sent by the current thread, it is nonzero; otherwise, it is zero.
lParam [in]
Type: LPARAM
A pointer to a CWPSTRUCT structure that contains details about the message.
Return value
Type: LRESULT
If nCode is less than zero, the hook procedure must return the value returned by CallNextHookEx.
If nCode is greater than or equal to zero, it is highly recommended that you call CallNextHookEx and return the value it returns; otherwise, other applications that have installed WH_CALLWNDPROC hooks will not receive hook notifications and may behave incorrectly as a result. If the hook procedure does not call CallNextHookEx, the return value should be zero. 
3.回调函数中应调用CallNextHookEx function,并将它返回的值返回给CallWndProc callback function,让消息能够传给其它勾子,如果CallWndProc callback function返回的是0,则将中止消息传递给其它勾子,建议返回CallNextHookEx的返回值,如果你愿意。
4.定义删除勾子的函数UnhookWindowsHookEx

 



5.要想安装全局勾子,应当定义在DLL动态链接库中
  完整代码
 
 1 library myHook;
 2
 3 uses
 4   System.SysUtils,
 5   Inifiles,
 6   System.Classes,
 7   Messages,  {消息 WM_LBUTTONDOWN 定义在 Messages 单元}
 8   windows; {钩子函数都来自 Windows 单元}
 9
10 {$R *.res}
11
12 var
13   hook:HHOOK;
14
15 function hookCallBack(nCode:Integer;wParam:WPARAM;lParam:LPARAM):LRESULT;stdcall;
16 var
17   me:CWPSTRUCT;//CallWndProc 缩写
18 begin
19     //处理 www.2cto.com
20     MessageBox(0,PCHAR(inttostr(wparam)),'提示',MB_OK);
21     Result:=CallNextHookEx(hook,nCode,wParam,lParam);
22 end;
23
24
25 function setHook:Boolean;stdcall;
26 begin
27   hook:=SetWindowsHookEx(WH_KEYBOARD,@hookCallBack,HInstance,0);
28   Result:=hook<>0;
29 end;
30
31 function deleteHook:boolean;stdcall;
32 begin
33   result:=UnhookWindowsHookEx(hook);
34 end;
35
36 {按 DLL 的要求输出函数}
37 exports
38   setHook name 'setHook',
39   deleteHook name 'deleteHook',
40   hookCallBack name 'hookCallBack';
41 begin
42 end.
 
6.调用DLL动态链接库中的函数来安装勾子
动态调用
先申明要调用的函数
1 type
2   TDLLFun = function: Boolean; stdcall;{定义和 DLL 中同样参数和返回值的的函数类型}
2)申明存储DLL句柄的变量和要调用函数的地址
1 var
2  h: HWND;                   {声明一个 DLL 句柄}
3  SetHook, DelHook: TDLLFun; {声明两个 TDLLFun 变量}
3)载入DLL文件,取得DLL中的函数地址,赋值给DelHook,和SetHook变量
 
 1 procedure TForm5.Button1Click(Sender: TObject);
 2 var
 3  b:Boolean;
 4 begin
 5   h := LoadLibrary('myHook.dll'); {载入 DLL 并获取句柄}
 6   if h<>0 then
 7   begin
 8     SetHook := GetProcAddress(h, 'setHook'); {让 SetHook 指向 DLL 中相应的函数}
 9     DelHook := GetProcAddress(h, 'deleteHook'); {让 DelHook 指向 DLL 中相应的函数}
10   end else ShowMessage('Err');
11   b:=SetHook; {执行钩子建立函数, 这里的 SetHook 和它指向的函数是同名的, 也可以不同名}
12 end;
 
4)程序关闭时删除勾子,释放DLL资源
1 procedure TForm5.Button2Click(Sender: TObject);
2 begin
3   DelHook;        {执行钩子释放函数}
4   FreeLibrary(h); {释放 DLL 资源}
5 end;
  调用勾子的全部代码
 
 1 unit Unit5;
 2
 3 interface
 4
 5 uses
 6   Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
 7   Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
 8
 9 type
10   TForm5 = class(TForm)
11     Button1: TButton;
12     Button2: TButton;
13     procedure Button1Click(Sender: TObject);
14     procedure Button2Click(Sender: TObject);
15   private
16     { Private declarations }
17   public
18     { Public declarations }
19   end;
20
21 var
22   Form5: TForm5;
23
24 implementation
25
26 {$R *.dfm}
27   {要先要定义和 DLL 中同样参数和返回值的的函数类型}
28 type
29   TDLLFun = function: Boolean; stdcall;
30   {现在需要的 DLL 中的函数的格式都是这样, 定义一个就够了}
31 var
32  h: HWND;                   {声明一个 DLL 句柄}
33  SetHook, DelHook: TDLLFun; {声明两个 TDLLFun 变量}
34
35
36 procedure TForm5.Button1Click(Sender: TObject);
37 var
38  b:Boolean;
39 begin
40   h := LoadLibrary('myHook.dll'); {载入 DLL 并获取句柄}
41   if h<>0 then
42   begin
43     SetHook := GetProcAddress(h, 'setHook'); {让 SetHook 指向 DLL 中相应的函数}
44     DelHook := GetProcAddress(h, 'deleteHook'); {让 DelHook 指向 DLL 中相应的函数}
45   end else ShowMessage('Err');
46   b:=SetHook; {执行钩子建立函数, 这里的 SetHook 和它指向的函数是同名的, 也可以不同名}
47 end;
48
49 procedure TForm5.Button2Click(Sender: TObject);
50 begin
51   DelHook;        {执行钩子释放函数}
52   FreeLibrary(h); {释放 DLL 资源}
53 end;
54
55 end.
 

 

作者 realnull

图片内容