程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> 使用鉤子函數[2]

使用鉤子函數[2]

編輯:Delphi

鉤子函數雖然不多, 但其參數復雜, 應該從參數入手才能深入進去.

UnhookWindowsHookEx 只需要 SetWindowsHookEx 返回的鉤子句柄作參數, 這個簡單;

先看看 SetWindowsHookEx 的聲明:

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

第一個參數非常麻煩, 從後面說:

參數四 dwThreadId : 在設置全局鉤子時這個參數一般是 0, 表示關聯所有線程; 本例是線程級的鉤子, 所以是

GetCurrentThreadId.

參數三 hmod: 是模塊實例的句柄, 在 EXE 和 DLL 中都可以用 HInstance 得到當前實例的句柄; 直接用 API 也可以:

GetModuleHandle(nil).

參數二 lpfn: 是鉤子函數的指針, 用 @ 和 Addr 函數都可以得到函數指針; 這裡的關鍵是那個鉤子函數:

首先不同的鉤子類型對應著不同的鉤子函數結構, Win32 共有 14 種鉤子類型, 這是 詳細注釋;

本例用的是鍵盤鉤子, 鍵盤鉤子的回調函數的參數結構在 這裡, 我們定義的函數名無所謂, 參數必須按照Windows的規定來.

還有, 這個回調函數的調用慣例必須是: stdcall; 我們在上例中是先在接口區聲明, 如果不要聲明直接實現, 也不能忘了這個 stdcall.

根據以上說明, 做如下修改:

SetWindowsHookEx 的參數有變通;

並且取消了鉤子函數在接口區的聲明, 是直接實現的;

取消了攔截條件, 現在只要是鍵盤消息全都攔截.

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;

type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

var
hook: HHOOK; {定義一個鉤子句柄}

{現在這個鉤子函數沒有在接口區聲明, 這裡必須指定參數調用方式: stdcall}
function KeyHook(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
Beep;
Result := CallNextHookEx(hook, nCode, wParam, lParam);
end;

{設置鍵盤鉤子}
procedure TForm1.FormCreate(Sender: TObject);
begin
hook := SetWindowsHookEx(WH_KEYBOARD, Addr(KeyHook), HInstance, GetCurrentThreadId);
end;

{釋放鍵盤鉤子}
procedure TForm1.FormDestroy(Sender: TObject);
begin
UnhookWindowsHookEx(hook);
end;

end.

鉤子函數為什麼非得使用 stdcall 調用機制? 因為鉤子函數不是被應用程序調用, 而是被系統調用的.

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved