Delphi中鼠标键盘钩子函数的应用

钩子是Windows中消息处理机制的一个要点,通过安装各种钩子,应用程序能够设置相应的子例程  
   
来监视系统里的消息传递以及在这些消息到达目的地之前截获它们并根据用户要求做出相应处理。钩子  
   
的种类很多其作用也不同,如键盘钩子可以截获键盘消息,鼠标钩子可以截获鼠标消息,外壳钩子可以  
   
截获启动和关闭应用程序的消息,日志钩子可以监视和记录输入事件。钩子分为线程专用钩子和全局钩  
   
子,线程专用钩子只监视指定的线程,要监视系统中的所有线程,必须用到全局钩子。对于全局钩子,  
   
钩子函数必须包含在独立的动态链接库(DLL)中,这样才能被各种相关联的应用程序调用。  
一、钩子函数简介  
            Windows提供API函数SetwindowsHookEx来建立一个Hook,通过这个函数可以将一个程序添加到Hook  
   
链中监视Windows消息,函数语法为:  
            SetwindowsHookEx   (idHook:Integer;lpfn:TFNHookProc;hmod:   HINST;dwThreadId:DWORD)  
            其中参数idHook指定建立的监视函数类型。通过Windows   MSDN帮助可以看到,SetwindowsHookEx函  
   
数提供15种不同的消息监视类型,而WH_JOURNALRECORD和WH_JOURNALPLAYBACK是用来监视键盘和鼠标操  
   
作的。参数lpfn指定消息函数,在相应的消息产生后,系统会调用该函数并将消息值传递给该函数供处  
   
理。函数的一般形式为:  
            Hookproc   (icode:Integer;wparam:WPARAM;lparam:LPARAM):LRESULT;stdcall;    
            其中icode为系统指示标记,wParam和lParam为附加参数,根据不同的消息监视类型而不同。只要  
   
在程序中建立这样一个函数再通过SetwindowsHookEx函数将它加入到消息监视链中就可以处理消息了。  
   
在不需要监视系统消息时可以调用UnHookWindowsHookEx来解除对消息的监视。WH_JOURNALRECORD和  
   
WH_JOURNALPLAYBACK类型是两种相反的Hook类型,前者获得鼠标、键盘动作消息,后者回放鼠标、键盘  
   
消息。  
             
二、钩子程序的实例  
            在本程序中建立了两个消息函数,一个用于纪录鼠标、键盘的动作并保存,另一个用于将保存的动  
   
作返给系统回放。在Delphi中建立一个工程,在Form1上添加3个按钮用于程序操作。另外再添加一个  
   
Edit控件用于验证操作

unit  Unit1;

interface

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

type
  TForm1 
=   class (TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Edit1: TEdit;
    
procedure  FormCreate(Sender: TObject);
    
procedure  Button1Click(Sender: TObject);
    
procedure  Button2Click(Sender: TObject);
    
procedure  Button3Click(Sender: TObject);
  
private
    
{  private   declarations  }
  
public
    
{  public   declarations  }
  
end ;

var
  Form1: TForm1;
  EventArr: 
array  [ 0  ..  1000 of  EVENTMSG;
  EventLog: Integer;
  PlayLog: Integer;
  hHook, hPlay: Integer;
  recOK: Integer;
  canPlay: Integer;
  bDelay: Bool;

implementation

{ $R   *.DFM }

function  PlayProc(iCode: Integer; wParam: wParam; lParam: lParam): LRESULT;
  
stdcall ;
begin
  canPlay :
=   1 ;
  Result :
=   0 ;
  
if  iCode  <   0   then   //  必须将消息传递到钩子链的下一个处理程序
    Result :
=  CallNextHookEx(hPlay, iCode, wParam, lParam)
  
else   if  iCode  =  HC_SYSMODALON  then
    canPlay :
=   0
  
else   if  iCode  =  HC_SYSMODALOFF  then
    canPlay :
=   1
  
else   if  ((canPlay  =   1 and  (iCode  =  HC_GETNEXT))  then
  
begin
    
if  bDelay  then
    
begin
      bDelay :
=  False;
      Result :
=   50 //  控制回放的速度,数字越大,越慢
    
end ;
    pEventMSG(lParam)^ :
=  EventArr[PlayLog];
  
end
  
else   if  ((canPlay  =   1 and  (iCode  =  HC_SKIP))  then
  
begin
    bDelay :
=  True;
    PlayLog :
=  PlayLog  +   1 ;
  
end ;
  
if  PlayLog  >=  EventLog  then
  
begin
    UNHookWindowsHookEx(hPlay);
  
end ;
end ;

function  HookProc(iCode: Integer; wParam: wParam; lParam: lParam): LRESULT;
  
stdcall ;
begin
  recOK :
=   1 //  可以记录
  Result :
=   0 ;
  
if  iCode  <   0   then   //  必须将消息传递到钩子链的下一个处理程序
    Result :
=  CallNextHookEx(hHook, iCode, wParam, lParam)
  
else   if  iCode  =  HC_SYSMODALON  then
    recOK :
=   0
  
else   if  iCode  =  HC_SYSMODALOFF  then
    recOK :
=   1
  
else   if  ((recOK  >   0 and  (iCode  =  HC_ACTION))  then
  
begin
    EventArr[EventLog] :
=  pEventMSG(lParam)^;
    EventLog :
=  EventLog  +   1 ;
    
if  EventLog  >=   1000   then
    
begin
      UNHookWindowsHookEx(hHook);
    
end ;
  
end ;
end ;

procedure  TForm1.FormCreate(Sender: TObject);
begin
  Button1.Caption :
=   ' 纪录 ' ;
  Button2.Caption :
=   ' 停止 ' ;
  Button3.Caption :
=   ' 回放 ' ;
  Button2.Enabled :
=  False;
  Button3.Enabled :
=  False;
end ;

procedure  TForm1.Button1Click(Sender: TObject);
begin
  EventLog :
=   0 ;
  
//  建立键盘、鼠标操作消息纪录链
  hHook :
=  SetwindowsHookEx(WH_JOURNALRECORD, HookProc, HInstance,  0 );
  Button2.Enabled :
=  True;
  Button1.Enabled :
=  False;
end ;

procedure  TForm1.Button2Click(Sender: TObject);
begin
  UNHookWindowsHookEx(hHook);
  hHook :
=   0 ;
  Button1.Enabled :
=  True;
  Button2.Enabled :
=  False;
  Button3.Enabled :
=  True;
end ;

procedure  TForm1.Button3Click(Sender: TObject);
begin
  PlayLog :
=   0 ;
  
//  建立键盘鼠标操作消息纪录回放链
  hPlay :
=  SetwindowsHookEx(WH_JOURNALPLAYBACK, PlayProc, HInstance,  0 );
  Button3.Enabled :
=  False;
end ;

end .

 

运行程序,点击“纪录”按钮开始纪录操作,这时你可以在文本控件中输入一些文字,然后点击“    
停止”按钮停止纪录,再点击“回放”按钮就可以将先前所做的操作回放。在上面的程序中,HookProc   
是纪录操作的消息函数,每当有鼠标、键盘消息发生时,系统都会调用该函数,消息信息就保存在地址     
lParam中,PlayProc是消息回放函数,当系统执行消息回放时调用该函数,程序就将先前纪录的消息值      
返回到lParam指向的区域中,系统就会执行该消息,从而实现了消息回放。                
三、小结  
Hook是应用程序在Microsoft   Windows   消息处理过程中设置的用来监控消息流并且处理系统中尚未  
到达目的窗口的某一类型消息过程的机制。这可以帮助应用程序实现实现某些特殊目的,如控制键盘或   
鼠标的输入消息,监视窗口的打开关闭以及实现记录宏等等,应用灵活,功能强大。如果Hook过程在应   
用程序中实现,若应用程序不是当前窗口时,该Hook就不起作用;如果Hook在DLL中实现,程序在运行中  
动态调用它,它能实时对系统进行监控.

转载于:https://www.cnblogs.com/rogee/archive/2010/09/15/1827311.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
简单的低级钩子做的应用实例,实现了开机自动启动功能,程序启动后在后台运行,等待本地QQ启动后,开启钩子,记录键盘输入的字符,并保存在D:盘目录下的指定名文档。关闭QQ时,钩子自动卸载并结束进程。 但是由于是使用的键盘钩子,所以只能简单的抓取键盘所键入的内容,如果是汉字的话则无法显示。 由于使用了Hook技术,并对注册表进行了修改,使用前请关闭360等防火墙软件,并使用管理员模式运行。 一次执行后,之后再次开机时,该程序会自动启动。 程序尚有缺陷,如内存泄漏,究其原因是CString应用在多线程导致,但至今未查到根源所在,希望大神指教,学生不胜感激! 也希望各位多提出宝贵意见,或对本程序进行开发改造。 个人暂时希望改造的几个方面: 1.首先是希望能够屏蔽掉360等防火墙的检查。更深层次的改造,希望能够主动杀死360等防火墙的进程。 2.其次是希望能够做成主辅进程相互监视的模式,主进程down掉后,辅进程自动能把主进程启动,辅助进程down掉后,主进程能把辅进程自动启动。 3.其次是希望能够做成真正的隐藏进程的风格,就是能够在任务管理器隐藏掉进程,其实可以做成服务,但是更希望能够以进程的形式存在。 4.然后很重要的是,希望能够做成自动获取管理员权限的类型,这个一直很想做,但是小菜我水平有限,暂时未对应。 5.希望对应网络开发,现在用钩子钩下来的文字,暂时只是保存在本地的一个txt文件,希望最终实现把抓下来的内容发送到指定邮箱这样的功能。 暂时就先想到这么多吧,希望大家多多提出宝贵意见。 (最终声明:本程序只限用于研究学习开发技术,不得用于研究学习以外的任何目的) 作者:Benjamin Wang 2013-12-02
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值