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