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.
1 HHOOK WINAPI SetWindowsHookEx(2 __in int idHook,//勾子类型3 __in HOOKPROC lpfn,//回调函数的地址4 __in HINSTANCE hMod,//一般为HInstance5 __in DWORD dwThreadId,//关联进程的句柄,如果0则关联所有正在运行的进程,全局勾子时为06 );
勾子类型为下面的值
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 lParam5 );
Parameters
nCode [in] Type: intSpecifies 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: WPARAMSpecifies 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: LPARAMA 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 var13 hook:HHOOK;14 15 function hookCallBack(nCode:Integer;wParam:WPARAM;lParam:LPARAM):LRESULT;stdcall;16 var17 me:CWPSTRUCT;//CallWndProc 缩写18 begin19 //處理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 begin27 hook:=SetWindowsHookEx(WH_KEYBOARD,@hookCallBack,HInstance,0);28 Result:=hook<>0;29 end;30 31 function deleteHook:boolean;stdcall;32 begin33 result:=UnhookWindowsHookEx(hook);34 end;35 36 { 按 DLL 的要求输出函数}37 exports38 setHook name 'setHook',39 deleteHook name 'deleteHook',40 hookCallBack name 'hookCallBack';41 begin42 end.
6.调用DLL动态链接库中的函数来安装勾子
动态调用
先申明要调用的函数
1 type2 TDLLFun = function: Boolean; stdcall;{ 定义和 DLL 中同样参数和返回值的的函数类型}
2)申明存储DLL句柄的变量和要调用函数的地址
1 var2 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 begin3 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 type10 TForm5 = class(TForm)11 Button1: TButton;12 Button2: TButton;13 procedure Button1Click(Sender: TObject);14 procedure Button2Click(Sender: TObject);15 private16 { Private declarations }17 public18 { Public declarations }19 end;20 21 var22 Form5: TForm5;23 24 implementation25 26 { $R *.dfm}27 { 要先要定义和 DLL 中同样参数和返回值的的函数类型}28 type29 TDLLFun = function: Boolean; stdcall;30 { 现在需要的 DLL 中的函数的格式都是这样, 定义一个就够了}31 var32 h: HWND; { 声明一个 DLL 句柄}33 SetHook, DelHook: TDLLFun; { 声明两个 TDLLFun 变量}34 35 36 procedure TForm5.Button1Click(Sender: TObject);37 var38 b:Boolean;39 begin40 h := LoadLibrary('myHook.dll'); { 载入 DLL 并获取句柄}41 if h<>0 then42 begin43 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 begin51 DelHook; { 执行钩子释放函数}52 FreeLibrary(h); { 释放 DLL 资源}53 end;54 55 end.