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

分享

學(xué)用鉤子函數(shù) - Qi

 ShangShujie 2007-05-03

學(xué)用鉤子函數(shù)

    鉤子函數(shù)并不是什么高深的技術(shù),在Microsoft的Win32 SDK手冊(cè)上就有記述。不過(guò)很可惜秉承M$的一貫風(fēng)格,要看懂可是不容易的事!而且它的例子是使用SDK寫的,又不完整!這就讓我們這些用只會(huì) Delphi的程序員更看不懂了。不過(guò)用鉤子函數(shù)是很有用的,例如鼠標(biāo)鉤子可以攔截下所有的鼠標(biāo)消息的。
    前段時(shí)間我寫我的第一個(gè)軟件《聊天快貼》的時(shí)候,學(xué)習(xí)了一下鼠標(biāo)鉤子函數(shù),現(xiàn)在我把我?guī)字艿膶W(xué)習(xí)成果寫出來(lái)希望對(duì)大家有幫助。
    鉤子函數(shù)一共有12種(這里就不列舉出來(lái)了,不過(guò)說(shuō)實(shí)話我多數(shù)鉤子也沒(méi)有用過(guò)^_^),分為全局子和線程鉤子兩種。線程鉤子就只監(jiān)視某個(gè)線程,全局鉤子可 以監(jiān)視Windows的所有線程。具體的你可以看看Delphi 帶的Win32 SDK,就是是全英文的,可惜了。全局鉤子是必須用DLL加載,也就是說(shuō)鉤子函數(shù)這部分必須包裝為一個(gè)DLL文件,然后再在主程序中調(diào)用鉤子DLL中函數(shù) 才可以!而且有些鉤子是必須以全局鉤子的方式存在,也就是一定要用DLL包裝它才可以。
再解釋一下設(shè)置鉤子的Api函數(shù):
function SetWindowsHookEx(idHook: Integer; lpfn: TFNHookProc; hmod: HINST; dwThreadId: DWORD): HHOOK; stdcall;這是在Delphi下的說(shuō)明,其中第一個(gè)參數(shù)是鉤子的類型;第二個(gè)參數(shù)是鉤子函數(shù)的地址;第個(gè)參數(shù)是包含鉤子函數(shù)的模塊句柄;第四個(gè)參數(shù) 指定監(jiān)視的線程;返回鉤子句柄。如果指定了某個(gè)確定的線程就只監(jiān)視那個(gè)線程,即是線程鉤子;如果為空,即是監(jiān)視所有線程的全局鉤子。其它幾個(gè)相關(guān)函數(shù)就沒(méi) 有什么講的了,只要照著用就可以了。具體的看我的源程序吧! 
    另外如果你只想使用進(jìn)程鉤子的話,有一個(gè)現(xiàn)成的控件可以用,就是Rx的RxWindowHook控件。拖到你窗體上,設(shè)置Active為True就可以 了。 然后他只有BeforeMessage(消息從消息隊(duì)列取走前)和AfterMessage(消息從消息隊(duì)列取走后)兩個(gè)事件,響應(yīng)他就可以了,怎么用就 看你的了。
    下面我說(shuō)說(shuō)比較實(shí)用的全局鉤子的使用!我寫了一個(gè)最簡(jiǎn)單的鼠標(biāo)全局鉤子的例子,我還假定你懂如何寫DLL。好了,來(lái)看源程序:(BTW:我學(xué)習(xí)編程技巧的時(shí)候總是想看一些最簡(jiǎn)單的例子,可是有些作者習(xí)慣用復(fù)雜的應(yīng)用作為例子。學(xué)起來(lái)真是痛苦!?。。?

一、DLL的工程文件。

library hookprj;

uses
  SysUtils,
  Classes,
  hkprocunit in ‘hkprocunit.pas‘;

{$R *.RES}
exports
  EnableMouseHook, //只要把這兩個(gè)函數(shù)輸出就可以了,
  DisableMouseHook;//不會(huì)不懂函數(shù)的意思吧^_^。
begin

end.

二、DLL輸出函數(shù)的實(shí)現(xiàn)單元。

unit hkprocunit;

interface

uses
  Windows,Messages;

var
  hHk: HHOOK;//鉤子的句柄值。
  function MouseHookProc(nCode: Integer;WParam: WPARAM;LParam: LPARAM):   LRESULT;stdcall;
  //鼠標(biāo)鉤子的回調(diào)函數(shù),即是用它來(lái)處理得到消息后要干什么。這里我只是發(fā)送  一個(gè)//WM_PASTE消息。
  //nCode參數(shù)是Hook的標(biāo)志,一般只關(guān)心小于0時(shí)。看下面的詳細(xì)說(shuō)明
  //WParam參數(shù)表示鼠標(biāo)消息的類型
  //LParam參數(shù)是一個(gè)指向 TMOUSEHOOKSTRUCT 結(jié)構(gòu)的指針。結(jié)構(gòu)包含了鼠標(biāo)消息的狀態(tài),我只用了hwnd一個(gè)
  //即鼠標(biāo)消息要傳遞給的窗口句柄。
  //返回值如果不是0的話windows就把這個(gè)消息丟掉,其它的程序就不會(huì)再收到這個(gè)消息了。

  function EnableMouseHook:Boolean; stdcall; export;
  function DisableMouseHook:Boolean; stdcall; export;//兩個(gè)函數(shù)都是Boolean類型,成功都是返回True

implementation

function MouseHookProc(nCode: Integer;WParam: WPARAM;LParam: LPARAM): LRESULT;stdcall;
var
  MouseHookStruct: ^TMOUSEHOOKSTRUCT;//這個(gè)結(jié)構(gòu)Delphi在Windows單元有定義,直接用就可以了。
  nState: SHORT;//得到鍵盤狀態(tài)的GetKeyState函數(shù)的返回值。這是一個(gè)16位的數(shù)。 
begin
  Result := 0; //最好首先給他一個(gè)返回值,不然會(huì)有警告的!記住這可不是C語(yǔ)言。
  //當(dāng)nCode小于0時(shí)表示還有其它的Hook,必須把參數(shù)傳給他。
  //此時(shí)就要用Api函數(shù)CallNextHookEx讓他調(diào)用下一個(gè)Hook!!!當(dāng)然不用好像也可以。 
  if nCode < 0 then 
    Result := CallNextHookEx(hHk,nCode,WParam,LParam)//參數(shù)是現(xiàn)成的,直接用就可以了,詳細(xì)的說(shuō)明可以參考Win32 SDK
  else if wParam = WM_LBUTTONDBLCLK then //判斷是不是鼠標(biāo)左鍵雙擊事件
  begin
    nState := GetKeyState(VK_CONTROL);//這個(gè)函數(shù)只有一個(gè)參數(shù),就是要得到的鍵的鍵值,這里用windows的虛擬鍵值表示ctrl鍵。
    if (nState and $8000) = $8000 then//如果按下了,那么返回值的最高位為1
    begin //即是16進(jìn)制的8000,如果沒(méi)有按下就返回0
      MouseHookStruct := Pointer(LParam);//轉(zhuǎn)換指針并付值給MouseHookStruct變量。
      SendMessage(MouseHookStruct.hwnd,WM_PASTE,0,0);//如果條件都滿足了就發(fā)送WM_PASTE(粘貼)消息
    end;
  end;

end;

function EnableMouseHook:Boolean; stdcall; export;
begin
  if hHk = 0 then //為了安全,必須判斷一下再設(shè)置鉤子。
  begin 
    // 第三個(gè)參數(shù)的Hinstance 在Delphi中有定義,用就可以了。第四個(gè)參數(shù)必須為0
    hHk := SetWindowsHookEx(WH_MOUSE,@MouseHookProc,Hinstance,0);
    Result := True;
  end
  else
    Result := False;
end;

function DisableMouseHook:Boolean; stdcall; export;
begin
  if hHk <> 0 then //如果有鉤子就卸掉他。
  begin
    UnHookWindowsHookEx(hHk);
    hHk := 0;
    Result := True;
  end
  else
    Result := False;
end;

end.

三、使用鉤子的應(yīng)用程序的工程文件。

program Project1;

uses
  Forms,
  Unit1 in ‘Unit1.pas‘ {Form1};

{$R *.RES}

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

四、使用鉤子的應(yīng)用程序代碼。

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, RxHook;

type
  TForm1 = class(TForm)
    Button1: TButton;//放上兩個(gè)Button和一個(gè)Edit控鍵用來(lái)試用我們的鉤子函數(shù)。
    Button2: TButton;
    Edit1: TEdit;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { private declarations }

  public
    { public declarations }
end;

var
  Form1: TForm1;
  //下面是引用hookprj.dll中的函數(shù)。
    function EnableMouseHook:Boolean; stdcall; external ‘Hookprj.dll‘ name ‘EnableMouseHook‘;
    function DisableMouseHook:Boolean; stdcall; external ‘Hookprj.dll‘ name ‘DisableMouseHook‘;
implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
begin
  if EnableMouseHook then
    ShowMessage(‘啟動(dòng)鉤子成功‘);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  if DisableMouseHook then
    ShowMessage(‘停止鉤子成功‘);
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  //這里調(diào)用是必須的,否則有可能沒(méi)有卸載鉤子就退出了,那就不好了。 
  DisableMouseHook;
end;
end.
Windows2000 + Delphi5.0sp1 測(cè)試通過(guò)

 



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1175414

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(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)論公約

    類似文章 更多