鼠标动作纪录与回放

Posted on 2009-08-11 17:09  唐工  阅读(2811)  评论(5)    收藏  举报
 很多的教学软件或系统监视软件可以自动记录回放用户的输入文字或点击按钮等操作操作,这个功能的实现是使用  
  了Windows的Hook函数。      
    
      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   (code:   Integer;   wparam:   WPARAM;   lparam:   LPARAM):   LRESULT   stdcall;  
      其中code为系统指示标记,wParam和lParam为附加参数,根据不同的消息监视类型而不同。只要在程序中建立这样  
  一个函数再通过SetwindowsHookEx函数将它加入到消息监视链中就可以处理消息了。  
      在不需要监视系统消息时需要调用提供UnHookWindowsHookEx来解除对消息的监视。  
      WH_JOURNALRECORD和WH_JOURNALPLAYBACK类型是两种相反的Hook类型,前者获得鼠标、键盘动作消息,后者回放鼠  
  标键盘消息。所以在程序中我们需要建立两个消息函数,一个用于纪录鼠标键盘操作并保存到一个数组中,另一个用于  
  将保存的操作返给系统回放。  
   
   
      下面来建立程序,在Delphi中建立一个工程,在Form1上添加3个按钮用于程序操作。另外再添加一个按钮控件和一  
  个Edit控件用于验证操作。  
   
   
      下面是Form1的全部代码       
  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;  
      Button4:   TButton; 
    
      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:='回放';  
      Button4.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指向的区域中,系统就会执行该消息,从而实现了消息回放。  

博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3