技術交流,DH講解.
今天進入這書第二章 鉤子(HOOK).
先說說鉤子是什麼?
鉤子其實就在你環境中加上一層過濾,在特殊情況下就觸發鉤子回呼函數.
比如說我們安裝了全域的鍵盤鉤子,那麼當我們按動鍵盤上面的鍵的時候,鉤子的回呼函數就會觸發.
我們也能看到本來是直來直往的,結果現在中間安裝了一層過濾,系統的效率肯定會有所下降的.
要瞭解,我們只需要知道3個函數:
1 上鉤函數:
function SetWindowsHookEx(idHook: Integer;//鉤子的類型 lpfn: TFNHookProc; //回呼函數指標hmod: HINST; //一般為0或者InstancedwThreadId: DWORD//全域鉤子就為0,不然就為指定進程id): HHOOK; stdcall;//成功就返回一個值,不成功就為0
其中鉤子類型有:
{$EXTERNALSYM WH_MIN} WH_MIN = -1; {$EXTERNALSYM WH_MSGFILTER} WH_MSGFILTER = -1; {$EXTERNALSYM WH_JOURNALRECORD} WH_JOURNALRECORD = 0; {$EXTERNALSYM WH_JOURNALPLAYBACK} WH_JOURNALPLAYBACK = 1; {$EXTERNALSYM WH_KEYBOARD} WH_KEYBOARD = 2; {$EXTERNALSYM WH_GETMESSAGE} WH_GETMESSAGE = 3; {$EXTERNALSYM WH_CALLWNDPROC} WH_CALLWNDPROC = 4; {$EXTERNALSYM WH_CBT} WH_CBT = 5; {$EXTERNALSYM WH_SYSMSGFILTER} WH_SYSMSGFILTER = 6; {$EXTERNALSYM WH_MOUSE} WH_MOUSE = 7; {$EXTERNALSYM WH_HARDWARE} WH_HARDWARE = 8; {$EXTERNALSYM WH_DEBUG} WH_DEBUG = 9; {$EXTERNALSYM WH_SHELL} WH_SHELL = 10; {$EXTERNALSYM WH_FOREGROUNDIDLE} WH_FOREGROUNDIDLE = 11; {$EXTERNALSYM WH_CALLWNDPROCRET} WH_CALLWNDPROCRET = 12; {$EXTERNALSYM WH_KEYBOARD_LL} WH_KEYBOARD_LL = 13; {$EXTERNALSYM WH_MOUSE_LL} WH_MOUSE_LL = 14; {$EXTERNALSYM WH_MAX} WH_MAX = 14; {$EXTERNALSYM WH_MINHOOK} WH_MINHOOK = WH_MIN; {$EXTERNALSYM WH_MAXHOOK} WH_MAXHOOK = WH_MAX;
具體作用基本上就看名字就知道,個別的我也不知道,具體的大家看MSDN吧.這個是個葵花寶典.
2 卸鉤函數:
function UnhookWindowsHookEx(hhk: HHOOK//上鉤函數返回的控制代碼): BOOL; stdcall;
3 具體的鉤子回呼函數:
TFNHookProc = function (code: Integer; wparam: WPARAM; lparam: LPARAM): LRESULT stdcall;
好的說了這麼多,看例子:
Var H: HHOOK;Function MyKeyBoardHookProc(Code: Integer; Wparam: WPARAM; Lparam: LPARAM): LRESULT Stdcall;Begin If Code = HC_ACTION Then Begin // wparam是virtal code // lparam要分位元組 ShowMessage(Format('點擊%D鍵%D次', [Wparam, Lparam And $0000FFFF])); End; // 一定要記得調用下一個鉤子,因為我們要知道可能這個東西不只是你要處理,別人也要處理, // 如果你處理,就不往下傳了,我也米有辦法...算你BT Result := CallNextHookEx(H, Code, Wparam, Lparam);End;Procedure TForm2.Button1Click(Sender: TObject);Begin H := SetWindowsHookEx(WH_KEYBOARD, MyKeyBoardHookProc, 0, GetCurrentThreadId);End;Procedure TForm2.Button2Click(Sender: TObject);Begin UnhookWindowsHookEx(H)End;
這個鉤子的例子,只對自己進程有效,如果我們想全域都有效,就是對別人的進程也有效,那麼我們需要將鉤子代碼寫到Dll裡面去.
接下來就示範全域鉤子吧.
Var H: HHOOK; ExeHandle: Cardinal; // 這個handle一定能要用記憶體映射出來,因為全域鍵盤鉤子話, // 只要程式一按鍵,dll就會載入到這個進程裡面了,所以就形成多進程情況,這裡我就不弄了Function MyKeyBoardProc(Code: Integer; Wparam: WPARAM; Lparam: LPARAM): LRESULT Stdcall;Begin If Code = HC_ACTION Then PostMessage(ExeHandle, WM_HOTKEY, Wparam, Lparam); // 這裡偷懶了,直接轉寄出去 Result := CallNextHookEx(H, Code, Wparam, Lparam)End;Function HookOn(AHandle: Cardinal): Boolean; Export; // 匯出它Begin ExeHandle := AHandle; H := SetWindowsHookEx(WH_KEYBOARD, MyKeyBoardProc, HInstance, 0); // 最後一個參數一定是0 Result := H <> 0; // 判斷是否成功End;Function HookOff(): Boolean;export;Begin Result := UnhookWindowsHookEx(H)End;
其他的api hook以後再講,這裡就大致講了下鉤子如何使用.希望能有點兒協助.