岁月联盟 - 技术社区 - BBS.SYUE.COM's Archiver

猪猪 发表于 2007-3-6 22:52

Windows钩子函数的详细资料

为什么选这个话题?因为跟踪MOUSE坐标很常见,容易又特别不容易,非常说明W

INDOWS95下编程的特点。

{ 如果您看不懂,请买DELPHI 2 UNLEASHED RMB133,当然他没这个程序,但有一

些写WIN HOOK必须具备的知识。本程序得到AIMING大虾的大力协助,事实上我的

程序是在他的基础上改写的,他的是从DELPHI HELP中改写出来的。调试程序花了

我两个礼拜,最好你能花同样的时间,那么你就会收获很多! }

第一步,建一DLL,DELPHI中NEW-》DLL SAVE AS GETKEY
[code]library getKey;

uses

uses

SysUtils,

Windows,

HookMain in 'hookmain.pas';

exports

OpenGetKeyHook,

CloseGetKeyHook,

GetPublicP;

begin

NextHook := 0;

procSaveExit := ExitProc;

DLLproc := @DLLMain;

ExitProc := @HookExit;

DLLMain(DLL_PROCESS_ATTACH);

end.[/code]

[b]第二步,建一UNIT ,HOOK MAIN。关键在于CreateFileMapping 和 消息 WM_NCM[/b]

[code]ouseMove, WM_MOUSEMOVE:

unit HookMain;

 

interface

uses Windows, Messages, Dialogs, SysUtils;

//type DataBuf = Array [1..2] of DWORD;

type mydata=record

data1:array [1..2] of DWORD;

data2:TMOUSEHOOKSTRUCT;

end;

var hObject : THandle;

pMem : Pointer;

NextHook: HHook;

procSaveExit: Pointer;

function HookHandler(iCode: Integer; wParam: WPARAM; lParam: LPARAM):

LRESULT; stdcall; export;

function OpenGetKeyHook(sender : HWND;MessageID : WORD) : BOOL; export

;

function CloseGetKeyHook: BOOL; export;

function GetPublicP : Pointer;stdcall; export;

Procedure DLLMain(dwReason:DWord); far;

procedure HookExit; far;

 

implementation

Procedure UnMapMem;

begin

if Assigned(pMem) then

begin

UnMapViewOfFile(pMem);

pMem := Nil

end;

end;

Procedure MapMem;

begin

hObject := CreateFileMapping($FFFFFFFF,Nil,Page_ReadWrite,0,$FFFF,pCha

r('_IOBuffer'));

if hObject = 0 then Raise Exception.Create('创建公用数据的Buffer不成功

!');

pMem := MapViewOfFile(hObject,FILE_MAP_WRITE,0,0,SizeOf(mydata));

// 1 or SizeOf(DataBuf) ????

// 创建SizeOf(DataBuf)的数据区

if not Assigned(pMem) then

begin

begin

UnMapMem;

Raise Exception.Create('创建公用数据的映射关系不成功!');

end;

end;

Procedure DLLMain(dwReason:DWord); far;

begin

Case dwReason of

DLL_PROCESS_ATTACH :

begin

pMem := nil;

hObject := 0;

MapMem; //以下的公有数据,如tHWND,tMessageID将直接使用本Buf.

end;

DLL_PROCESS_DETACH : UnMapMem;

DLL_THREAD_ATTACH,

DLL_THREAD_DETACH :; //缺省

end;

end;

procedure HookExit; far;

begin

CloseGetKeyHook;

ExitProc := procSaveExit;

end;

function GetPublicP : Pointer;export;

begin //这里引出了公用数据区的指针,你可以在你的应用程序中自由操作它。

但建议去掉此接口。

Result := pMem;

end;

function HookHandler(iCode: Integer; wParam: WPARAM; lParam: LPARAM):

LRESULT; stdcall; export;

begin

Result := 0;

If iCode < 0

Then Result := CallNextHookEx(NextHook, iCode, wParam, lParam);

 

// This is probably closer to what you would want to do...

case wparam of

WM_LBUTTONDOWN:

begin

end;

end;

WM_LBUTTONUP:

begin

end;

WM_LBUTTONDBLCLK:

begin

end;

WM_RBUTTONDOWN:

begin

messagebeep(1);

end;

WM_RBUTTONUP:

begin

end;

WM_RBUTTONDBLCLK:

begin

end;

WM_MBUTTONDOWN:

begin

end;

WM_MBUTTONUP:

begin

end;

end;

WM_MBUTTONDBLCLK:

begin

end;

WM_NCMouseMove, WM_MOUSEMOVE:

begin

mydata(pmem^).data2:=pMOUSEHOOKSTRUCT(lparam)^;

// messagebeep(1);

//SendMessage(DataBuf(pMem^)[1],DataBuf(pMem^)[2],wParam,lParam );

SendMessage(mydata(pMem^).data1[1],mydata(pMem^).data1[2],wParam,integ

er(@(mydata(pmem^).data2)) );

end;

end; //发送消息

end;

function OpenGetKeyHook(sender : HWND;MessageID : WORD) : BOOL; export

;

begin

Result := False;

if NextHook <> 0 then Exit; //已经安装了本钩子

// DataBuf(pMem^)[1] := Sender; //填数据区

// DataBuf(pMem^)[2] := MessageID; //填数据区

mydata(pmem^).data1[1]:=sender;

mydata(pmem^).data1[2]:=messageid;

NextHook := SetWindowsHookEx(WH_mouse, HookHandler, HInstance, 0);

Result := NextHook <> 0;

end;

function CloseGetKeyHook: BOOL; export;

begin

if NextHook <> 0 then

begin

UnhookWindowshookEx(NextHook); //把钩子链链接到下一个钩子处理上.

NextHook := 0;

end;

Result := NextHook = 0;

end;

end.[/code]
[b]第三步,测试DLL,建一PROJECT。关键在于override WndProc[/b]
[code]unit Unit1;

interface

uses

Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialo

gs,

StdCtrls, ExtCtrls;

type

TForm1 = class(TForm)

uncapture: TButton;

capture: TButton;

Exit: TButton;

Panel1: TPanel;

show: TLabel;

Label1: TLabel;

counter: TLabel;

procedure ExitClick(Sender: TObject);

procedure uncaptureClick(Sender: TObject);

procedure captureClick(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

procedure WndProc(var Message: TMessage); override;

end;

var

Form1: TForm1;

var num : integer;

const MessageID = WM_User + 100;

implementation

{$R *.DFM}

function OpenGetKeyHook(sender : HWND;MessageID : WORD) : BOOL; extern

al 'GetKey.DLL';

function CloseGetKeyHook: BOOL; external 'GetKey.DLL';

procedure TForm1.ExitClick(Sender: TObject);

begin

close;

end;

end;

procedure TForm1.uncaptureClick(Sender: TObject);

begin

if CloseGetKeyHook then //ShowMessage('结束记录...');

show.caption:='结束记录...';

end;

procedure TForm1.captureClick(Sender: TObject);

begin

// if OpenGetKeyHook(self.Handle,MessageID) then ShowMessage('开始记录

...');

if OpenGetKeyHook(Form1.Handle,MessageID) then

//ShowMessage('开始记录...');

show.caption:='开始记录...';

num := 0;

 

end;

procedure TForm1.WndProc(var Message: TMessage);

var x,y:integer;

begin

if Message.Msg = MessageID then

begin

// Panel1.Caption := IntToStr(Num);

x:=PMouseHookStruct( message.lparam)^.pt.x ;

y:=PMouseHookStruct( message.lparam)^.pt.y ;

panel1.caption:='x='+inttostr(x)+' y='+inttostr(y);

inc(Num);

counter.Caption := IntToStr(Num);

end

else Inherited;

end;

end.[/code]

页: [1]

Powered by Discuz! Archiver 6.1.0  © 2001-2007 Comsenz Inc.