日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

Delphi 鉤子(1)

 aaie_ 2016-07-22

1. 鉤子函數(shù)  :  

 如果要設(shè)置系統(tǒng)級(jí)鉤子, 鉤子函數(shù)必須在 DLL 中.

1. SetWindowsHookEx - 設(shè)置鉤子   

2. UnhookWindowsHookEx - 卸掉鉤子

UnhookWindowsHookEx( 

         hhk: HHOOK {鉤子句柄}

):  BOOL;    {True/False}

3. CallNextHookEx - 調(diào)用下一個(gè)鉤子

CallNextHookEx( 

       hhk: HHOOK;    {當(dāng)前鉤子的句柄} 

       nCode: Integer; {鉤子代碼; 就是給下一個(gè)鉤子要交待的} 

      wParam: WPARAM; {要傳遞的參數(shù); 由鉤子類型決定是什么參數(shù)} 

      lParam: LPARAM  {要傳遞的參數(shù); 由鉤子類型決定是什么參數(shù)}

): LRESULT;      {會(huì)返回下一個(gè)鉤子執(zhí)行后的返回值; 0 表示失敗}

鉤子回調(diào)函數(shù)之 MsgFilterProc  鉤子回調(diào)函數(shù)之 JournalRecordProc  鉤子回調(diào)函數(shù)之 JournalPlaybackProc  鉤子回調(diào)函數(shù)之 GetMsgProc  鉤子回調(diào)函數(shù)之 CBTProc

目前對(duì)鉤子的理解:

譬如我們用鼠標(biāo)在某個(gè)窗口上雙擊了一次, 或者給某個(gè)窗口輸入了一個(gè)字母 A;
首先發(fā)現(xiàn)這些事件的不是窗口, 而是系統(tǒng)!

然后系統(tǒng)告訴窗口: 喂! 你讓人點(diǎn)了, 并且是連續(xù)點(diǎn)了兩鼠標(biāo), 你準(zhǔn)備怎么辦?
或者是系統(tǒng)告訴窗口: 喂! 有人向你家里扔磚頭了, 不信你看看, 那塊磚頭是 A.

這時(shí)窗口的對(duì)有些事件會(huì)忽略、對(duì)有些事件會(huì)做出反應(yīng):
譬如, 可能對(duì)鼠標(biāo)單擊事件忽略, 窗口想: 你單擊我不要緊, 累死你我不負(fù)責(zé);
但一旦誰要雙擊我, 我會(huì)馬上行動(dòng), 給你點(diǎn)顏色瞧瞧!
這里窗口準(zhǔn)備要采取的行動(dòng), 就是我們提前寫好的事件.
用 Windows 的話說, 窗口的事件就是系統(tǒng)發(fā)送給窗口的消息; 窗口要采取的行動(dòng)(事件代碼)就是窗口的回調(diào)函數(shù).

但是! 往往隔墻有耳. 系統(tǒng)要通知給窗口的"話"(消息), 可能會(huì)被另一個(gè)家伙(譬如是一個(gè)賊)提前聽到!
有可能這個(gè)賊就是專門在這等情報(bào)的, 賊知道后, 往往在窗口知道以前就采取了行動(dòng)!
并且這個(gè)賊對(duì)不同的消息會(huì)采取不同的行動(dòng)方案, 它的行動(dòng)方案一般也是早就準(zhǔn)備好的;
當(dāng)然這個(gè)賊也不是對(duì)什么消息都感興趣, 對(duì)不感興趣的消息也就無須制定相應(yīng)的行動(dòng)方案.

總結(jié): 這個(gè)"賊"就是我們要設(shè)置的鉤子; "賊"的"行動(dòng)方案"就是鉤子函數(shù), 或者叫鉤子的回調(diào)函數(shù).



鉤子分兩種, 一種是系統(tǒng)級(jí)的全局鉤子; 一種是線程級(jí)的鉤子.
全局鉤子函數(shù)需要定義在 DLL 中, 從線程級(jí)的鉤子開始比較簡單.

其實(shí)鉤子函數(shù)就三個(gè):
設(shè)置鉤子:
SetWindowsHookEx
釋放鉤子: UnhookWindowsHookEx
繼續(xù)鉤子: CallNextHookEx
在線程級(jí)的鉤子中經(jīng)常用到 GetCurrentThreadID 函數(shù)來獲取當(dāng)前線程的 ID.

下面例子中設(shè)定了一個(gè)線程級(jí)的鍵盤鉤子, 專門攔截字母 A.

 

[delphi] view plain copy
  1. <span style="font-size:18px;">{聲明鍵盤鉤子回調(diào)函數(shù); 其參數(shù)傳遞方式要用 API 的 stdcall}  
  2. function KeyHook(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;  
  3.   
  4. var  
  5.   Form1: TForm1;  
  6.   
  7. implementation  
  8.   
  9. {$R *.DFM}  
  10.   
  11. var  
  12.   hook: HHOOK; {定義一個(gè)鉤子句柄}  
  13.   
  14. {實(shí)現(xiàn)鍵盤鉤子回調(diào)函數(shù)}  
  15. function KeyHook(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT;  
  16. begin  
  17.   if (wParam = 65then Beep; {每攔截到字母 A 會(huì)發(fā)聲}  
  18.   Result := CallNextHookEx(hook, nCode, wParam, lParam);  
  19. end;  
  20.   
  21. {設(shè)置鍵盤鉤子}  
  22. procedure TForm1.FormCreate(Sender: TObject);  
  23. begin  
  24.   hook := SetWindowsHookEx(WH_KEYBOARD, @KeyHook, 0, GetCurrentThreadID);  
  25. end;  
  26.   
  27. {釋放鍵盤鉤子}  
  28. procedure TForm1.FormDestroy(Sender: TObject);  
  29. begin  
  30.   UnhookWindowsHookEx(hook);  
  31. end;  
  32.   
  33. </span>  

先看看 SetWindowsHookEx 的聲明:

SetWindowsHookEx(
  idHook: Integer;   {鉤子類型}
  lpfn: TFNHookProc; {函數(shù)指針}
  hmod: HINST;       {包含鉤子函數(shù)的模塊(EXE、DLL)的句柄}
  dwThreadId: DWORD  {關(guān)聯(lián)的線程}
): HHOOK;

第一個(gè)參數(shù)非常麻煩, 從后面說:

參數(shù)四 dwThreadId : 在設(shè)置全局鉤子時(shí)這個(gè)參數(shù)一般是 0, 表示關(guān)聯(lián)所有線程; 本例是線程級(jí)的鉤子, 所以是
GetCurrentThreadId.

參數(shù)三 hmod: 是模塊實(shí)例的句柄, 在 EXE 和 DLL 中都可以用 HInstance 得到當(dāng)前實(shí)例的句柄; 直接用 API 也可以:
GetModuleHandle(nil).

參數(shù)二 lpfn: 是鉤子函數(shù)的指針, 用 @ 和 Addr 函數(shù)都可以得到函數(shù)指針; 這里的關(guān)鍵是那個(gè)鉤子函數(shù):
首先不同的鉤子類型對(duì)應(yīng)著不同的鉤子函數(shù)結(jié)構(gòu), Win32 共有 14 種鉤子類型, 這是
詳細(xì)注釋;
本例用的是鍵盤鉤子, 鍵盤鉤子的回調(diào)函數(shù)的參數(shù)結(jié)構(gòu)在
這里, 我們定義的函數(shù)名無所謂, 參數(shù)必須按照Windows的規(guī)定來.
還有, 這個(gè)回調(diào)函數(shù)的調(diào)用慣例必須是: stdcall; 我們?cè)谏侠惺窍仍诮涌趨^(qū)聲明, 如果不要聲明直接實(shí)現(xiàn), 也不能忘了這個(gè) stdcall.

根據(jù)以上說明, 做如下修改:
SetWindowsHookEx 的參數(shù)有變通;
并且取消了鉤子函數(shù)在接口區(qū)的聲明, 是直接實(shí)現(xiàn)的;
取消了攔截條件, 現(xiàn)在只要是鍵盤消息全都攔截.

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多