为什么选这个话题?因为跟踪MOUSE坐标很常见,容易又特别不容易,非常说明WINDOWS95下编程的特点。
{ 如果您看不懂,请买DELPHI 2 UNLEASHED RMB133,当然他没这个程序,但有一些写WIN HOOK必须具备的知识。本程序得到AIMING大虾的大力协助,事实上我的程序是在他的基础上改写的,他的是从DELPHI HELP中改写出来的。调试程序花了我两个礼拜,最好你能花同样的时间,那么你就会收获很多! }
第一步,建一DLL,DELPHI中NEW-》DLL SAVE AS GETKEY
 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.
 第二步,建一UNIT ,HOOK MAIN。关键在于CreateFileMapping 和 消息 WM_NCM
 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.
 第三步,测试DLL,建一PROJECT。关键在于override WndProc
 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.