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动态链接库中
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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 //處理 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;
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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.