上传用户:yhtxzxm
上传日期:2007-01-04
资源大小:169k
文件大小:7k
源码类别:

钩子与API截获

开发平台:

Delphi

  1.                        用Delphi实现Windows的鼠标钩子函数
  2.     Delphi是基于PASCAL语言的Windows编程工具,功能十分强大。然而在Delphi的帮助
  3. 文件中,对Windows API函数的说明沿袭了 VC 的格式,和VC一样,对很多API函数的用法
  4. 没有举例子详细说明,对一些深入系统内部的API函数更是语焉不详,给编程者带来不便。
  5. 笔者仅就在Windows编程中鼠标钩子函数(HOOK)的实现,举例作一说明。
  6.    鼠标钩子函数也可叫做鼠标消息过滤器,是一种回调(CALLBACK)函数,归
  7. 系统调用。如果用SetWindowsHook或SetWindowsHookEx安装了鼠标钩子函数的地址, 每
  8. 当在屏幕上移动鼠标时,系统便将控制权交给鼠标钩子函数,这样便使我们能够有机会在
  9. 鼠标钩子函数内部截获各种鼠标消息,在这些消息还没有送达应用程序队列之前,显示它
  10. 们,改变它们或直接传给下一个缺省鼠标钩子函数。注意,鼠标钩子函数截获的是系统级
  11. 消息,而不是单个应用程序队列内的窗口消息;系统发给每个应用程序队列的鼠标消息都
  12. 可以用鼠标钩子函数来截获。
  13.     VC的Spy和Delphi的WinSpy均安装了钩子函数用来截获各种系统级的消息,其中就
  14. 包括鼠标钩子函数,键盘钩子函数,窗口钩子函数等。我们可以通过安装鼠标钩子函数来
  15. 仿制一个自己的SPY,当鼠标移动时,我们立即获得系统(包括非抢先的Windows3.1和
  16. 抢先Windows95)的控制权,在鼠标钩子函数内部实时地截获鼠标消息,显示鼠标的位置
  17. 和状态以及鼠标下窗口的局柄,标题栏,窗口类,窗口过程地址等。当然也可象“英汉通”
  18. 和“金山词霸”一样在鼠标钩子函数内调用InvalidateRect(),InvalidateRgn()来获得屏
  19. 幕上鼠标下的单词。(屏幕抓字的详情请见笔者的《深入Windows内部探险》中国计算机报
  20. 1998年第81期 )。
  21.    
  22.     主程序SPY及其动态连接库MOUSEDLL的原代码和详细注释如下:
  23. {*****************************************************
  24.  FILE   :  MOUSEDLL.DPR   mafeitao@371.net 1998/11/18
  25.  〉DLL  :  MOUSEDLL.DLL
  26.  EXPORT: sethook      用来安装鼠标钩子函数 mouseproc
  27.          unhook       解除对鼠标钩子函数 mouseproc的安装
  28.          mouseproc    鼠标钩子函数本身
  29.  *****************************************************}
  30. library Mousedll;
  31. uses
  32.   Mousep in 'MOUSEP.PAS' {Form1};
  33. exports
  34. sethook,
  35. unhook,
  36. mouseproc;
  37. {$R *.RES}
  38. begin
  39. end.
  40. {*************************************************************
  41.  file:Mousep.pas                      mafeitao@371.net
  42.  实现 setHook  unHook mouseProc 3个输出函数
  43.  *************************************************************}
  44. unit Mousep;
  45. interface
  46. uses
  47.   SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  48.   Forms, Dialogs, StdCtrls;
  49. {在DLL中也可有FORM型的变量}
  50. type
  51.   TForm1 = class(TForm)
  52.     Label1: TLabel;  {显示wParam}
  53.     Label2: TLabel;  {显示lParam}
  54.     Label3: TLabel;  {显示x,y}
  55.     Label4: TLabel;  {显示hwnd}
  56.     Label5: TLabel;  {显示window text}
  57.     Label6: TLabel;
  58.     Label7: TLabel;  {显示window class}
  59.   private
  60.     { Private declarations }
  61.   public
  62.     { Public declarations }
  63.   end;
  64. function sethook:bool;export;
  65. function unhook:bool;export;
  66. function mouseProc(code:integer;w:integer;l:longint):bool;export;
  67. var
  68.   Form1: TForm1;
  69.   idhook:longint;
  70.   formok:bool;
  71. implementation
  72.  {*********************************************************************
  73.  声明安装函数setWindowsHookEx(),
  74.  在Delphi中如果用函数setWindowsHook()则不需声明。
  75.  微软说函数setWindowsHook已在Windows3.1中废弃,为与Windows3.0兼容仍保留。
  76.  实际上该函数setWindowsHook在Windows3.1和Windows95中仍可使用。
  77.  {*********************************************************************}
  78.  function setwindowsHookEx(id:integer;proc:tfarproc;hinst,htask:thandle):
  79.          longint;far;external 'user';
  80. {$R *.DFM}
  81. {安装鼠标钩子函数mouseProc}
  82. function sethook:bool;
  83. var
  84. hinst:thandle;    {该动态连接库自己的模块局柄}
  85. proc:tfarproc;    {鼠标钩子函数mouseProc的地址}
  86. begin
  87. {在动态连接库中创建form1}
  88. if formok=false then form1:=tform1.create(application) else exit;
  89. formok:=true;{安装form1 后,设置formok,不许再安装form1}
  90. {动态连接库的application指:调用动态连接库的主程序}
  91. form1.show;
  92. {不让用系统菜单来双击关闭Form1}
  93. form1.BorderIcons:=form1.BorderIcons-[biSystemMenu];
  94. hinst:=getModuleHandle('mousedll');
  95. {得到mousedll.dll的模块局柄,即该动态连接库自己的模块局柄}
  96. proc:=getProcAddress(hinst,'mouseProc');
  97. idhook:=setWindowsHookEx(WH_MOUSE,proc,hinst,0);
  98. {用WH_MOUSE参数安装鼠标钩子后,移动鼠标时,系统自动调用mouseProc钩子}
  99. if idhook =0 then sethook:=false else sethook:=true;
  100. end;
  101. {解除鼠标钩子函数mouseProc的安装}
  102. function unhook:bool;
  103. begin
  104. if formok=true then form1.free else exit; {检查form1是否已经关闭}
  105. formok:=false;{关闭了form1,设置formok=0}
  106. if idhook=0 then exit;
  107. unhookWindowsHookEx(idhook);
  108. unhook:=true;
  109. end;
  110. {mouseProc不由应用程序调用,而是在鼠标移动后,由系统调用}
  111. function  mouseProc(code:integer;w:integer;l:longint):bool;
  112. var
  113. p:^TMouseHookStruct;
  114. poff:word;
  115. pseg:word;
  116. pmemo:pchar;
  117. begin
  118. if code<0 then begin
  119.     mouseProc:=true;
  120.     CallNextHookEx(idhook,0,w,l);
  121. end;
  122. if code=HC_NOREMOVE then form1.caption:='HC_NOREMOVE';
  123. form1.caption:='mouse hook';
  124. mouseProc:=false;
  125. {显示系统传来的wParam参数,w是各种鼠标消息的标识符  }
  126. form1.label1.caption:='wParam='+intTostr(w);
  127. {显示系统传来的lParam参数,l是MOUSEHOOKSTRUCT结构的地址}
  128. form1.label2.caption:='lParam='+intTostr(l);
  129. poff:=loword(l);     {得到l的低16位}
  130. pseg:=hiword(l);     {得到l的高16位}
  131. p:=ptr(pseg,poff);   {合成指向MOUSEHOOKSTRUCT结构的指针}
  132. {显示屏幕上鼠标的X,Y坐标}
  133. form1.label3.caption:='pt.x='+intTostr(p^.pt.x)
  134.      +'  pt.y='+intTostr(p^.pt.y);
  135. {显示屏幕上鼠标下的窗口局柄}
  136. form1.label4.caption:='hwnd='+intTostr(P^.hwnd);
  137. pmemo:=stralloc(20);
  138. getWindowText(p^.hwnd,pmemo,20-1);
  139. {显示鼠标下窗口的标题栏}
  140. form1.label5.caption:=strPas(pmemo);
  141. getClassName(p^.hwnd,pmemo,20-1);
  142. {显示鼠标下窗口的类}
  143. form1.label6.caption:=strPas(pmemo);
  144. strDispose(pmemo);
  145. end;
  146. end.
  147. 主程序原代码如下:
  148. {*******************************************
  149.  MAINTRY.DPR               mafeitao@371.net
  150.  ******************************************}
  151. program Maintry;
  152. uses
  153.   Forms,
  154.   Tryp in 'TRYP.PAS' {Form1};
  155. {$R *.RES}
  156. begin
  157.   Application.CreateForm(TForm1, Form1);
  158.   Application.Run;
  159. end.
  160. {*********************************************
  161.  TRYP.PAS                    mafeitao@371.net
  162.  ********************************************}
  163. unit Tryp;
  164. interface
  165. uses
  166.   SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  167.   Forms, Dialogs, StdCtrls;
  168. type
  169.   TForm1 = class(TForm)
  170.     Button1: TButton;       { 安装setHook按钮}
  171.     Button2: TButton;       { 解除 unHook按钮}
  172.     Label1: TLabel;         {显示安装,解除是否成功}
  173.     procedure Button1Click(Sender: TObject);
  174.     procedure Button2Click(Sender: TObject);
  175.   private
  176.     { Private declarations }
  177.   public
  178.     { Public declarations }
  179.   end;
  180. var
  181.   Form1: TForm1;
  182. implementation
  183. function sethook:bool;far;external 'mousedll';
  184. function unhook:bool;far;external 'mousedll'; 
  185.   {声明后自动加载模块mousedll.dll}
  186. {$R *.DFM}
  187. procedure TForm1.Button1Click(Sender: TObject);
  188. begin
  189. if sethook then label1.caption:='set hook ok'; {安装鼠标钩子函数}
  190. end;
  191. procedure TForm1.Button2Click(Sender: TObject);
  192. begin
  193. if unhook then label1.caption:='unhook ok';    {解除鼠标钩子函数}
  194. end;
  195. end.