【笨嘴拙舌WINDOWS】实践检验之按键精灵【Delphi】

通过记录键盘和鼠标位置和输入信息,然后模拟发送,就能够创建一个按键精灵!

主要代码如下:

 1 library KeyBoardHook;

 2 

 3 { Important note about DLL memory management: ShareMem must be the

 4   first unit in your library's USES clause AND your project's (select

 5   Project-View Source) USES clause if your DLL exports any procedures or

 6   functions that pass strings as parameters or function results. This

 7   applies to all strings passed to and from your DLL--even those that

 8   are nested in records and classes. ShareMem is the interface unit to

 9   the BORLNDMM.DLL shared memory manager, which must be deployed along

10   with your DLL. To avoid using BORLNDMM.DLL, pass string information

11   using PChar or ShortString parameters. }

12 

13 uses

14   SysUtils,

15   Classes,

16   Windows,

17   Messages;

18 

19   type

20     TCallBackFun=procedure(info:PChar);

21     TKeyBoardHook=record

22       isrun:Bool;

23       hook:HHook;

24       callBackFun:TCallBackFun;

25     end;

26 

27 var

28   myKeyBoardHook:TKeyBoardHook;

29 {$R *.res}

30 

31 function GetKeyBoardInfo(code:Integer;wp:WPARAM;lp:LPARAM):LRESULT;stdcall;

32 var

33   info:string;

34 begin

35   if code<0 then

36   begin

37     Result:=CallNextHookEx(myKeyBoardHook.hook,code,wp,lp);

38     Exit;

39   end;

40   info:='';

41   if ((DWord(lp) shr 31)=1) and (code=HC_ACTION) then

42     if ((DWord(lp) shr 29)=1) then

43       info:='WM_SYSKEYUP'

44     else

45       info:='WM_KEYUP'

46   else

47     if ((DWord(lp) shr 29)=1) then

48       info:='WM_SYSKEYDOWN'

49     else

50       info:='WM_KEYDOWN';

51   info:=info+','+inttostr(wp)+','+inttostr(lp);

52   if Assigned(myKeyBoardHook.callbackFun) then

53     myKeyBoardHook.callbackFun(pchar(info));

54   Result := CallNextHookEx(myKeyBoardHook.hook,code,wp,lp);

55 end;

56 

57 procedure InstallKeyBoardHook(callback:TCallBackFun);stdcall;

58 begin

59   if not myKeyBoardHook.isrun then

60   begin 

61     myKeyBoardHook.hook:=SetWindowsHookEx(WH_KEYBOARD,@GetKeyBoardInfo,HInstance,0);

62     myKeyBoardHook.callBackFun:=callBack;

63     myKeyBoardHook.isrun:=not myKeyBoardHook.isrun;

64   end;

65 end;

66 

67 procedure UninstallKeyBoardHook();stdcall;

68 begin

69   if   myKeyBoardHook.isrun   then

70   begin

71     UnHookWindowsHookEx(myKeyBoardHook.hook);

72     myKeyBoardHook.callBackFun:=nil;

73     myKeyBoardHook.isrun:=not myKeyBoardHook.isrun;

74   end;

75 end;

76 

77 Procedure DLLEntryPoint(dwReason:DWord);

78 begin

79   Case dwReason of

80     DLL_PROCESS_ATTACH:begin

81       myKeyBoardHook.isrun:=false;

82     end;

83     DLL_PROCESS_DETACH:;

84     DLL_THREAD_ATTACH:;

85     DLL_THREAD_DETACH:;

86   End;

87 end;

88 

89 exports

90   InstallKeyBoardHook,

91   UninstallKeyBoardHook;

92 

93 begin

94   DLLProc := @DLLEntryPoint;

95   DLLEntryPoint(DLL_PROCESS_ATTACH);

96 end.

以上是创建一个全局钩子函数的Dll来记录按键信息

library Mousehook;



{ Important note about DLL memory management: ShareMem must be the

  first unit in your library's USES clause AND your project's (select

  Project-View Source) USES clause if your DLL exports any procedures or

  functions that pass strings as parameters or function results. This

  applies to all strings passed to and from your DLL--even those that

  are nested in records and classes. ShareMem is the interface unit to

  the BORLNDMM.DLL shared memory manager, which must be deployed along

  with your DLL. To avoid using BORLNDMM.DLL, pass string information

  using PChar or ShortString parameters. }



uses

  SysUtils,

  Classes,

  Windows,

  Messages,

  ShellAPI;



  type

    TCallbackFun=procedure(info:pchar);

    TMouseHook=record

      isrun:Bool;

      hook:HHook;

      callbackFun:TCallbackFun;

    end;



var

  myMouseHook:TMouseHook;



{$R *.res}

//1.定义自定义的HOOK函数,函数必须和需要HOOK的钩子类型保持同样的参数列表

function GetHookInfo(code:Integer;wp:WPARAM;lp:LPARAM):LResult;stdcall;

var

  info:String;

begin

  if code<0 then

  begin

    Result:=CallNextHookEx(myMouseHook.hook,code,wp,lp);

    Exit;

  end;

  info:='';

  case wp of

    //鼠标消息共有21种,其中10种点击是客户区,10种是非客户区也就是消息名以NC开头的消息。和一个命中测试消息

    WM_LBUTTONDOWN:begin

      info:='WM_LBUTTONDOWN';

    end;

    WM_LBUTTONUP:begin

      info:='WM_LBUTTONUP';

    end;

    WM_LBUTTONDBLCLK:begin

      info:='WM_LBUTTONDBLCLK';

    end;

    WM_RBUTTONDOWN:begin

      info:='WM_RBUTTONDOWN';

    end;

    WM_RBUTTONUP:begin

      info:='WM_RBUTTONUP';

    end;

    WM_RBUTTONDBLCLK:begin

      info:='WM_RBUTTONDBLCLK';

    end;

    WM_MBUTTONDOWN:begin

      info:='WM_MBUTTONDOWN';

    end;

    WM_MBUTTONUP:begin

      info:='WM_MBUTTONUP';

    end;

    WM_MBUTTONDBLCLK:begin

      info:='WM_MBUTTONDBLCLK';

    end;

    WM_MOUSEMOVE:begin

      info:='WM_MOUSEMOVE';

    end;

    WM_NCMouseMove:begin

      info:='WM_NCMouseMove';

    end;

    WM_MOUSEWHEEL:

    begin

       info:='WM_MOUSEWHEEL';

    end;

    WM_NCHITTEST:begin

      info:='WM_NCHITTEST';

    end;

    WM_NCLBUTTONDOWN:BEGIN

      info:='WM_NCLBUTTONDOWN';

    end;

    WM_NCLBUTTONUP:BEGIN

      info:='WM_NCLBUTTONUP';

    end;

    WM_NCLBUTTONDBLCLK:BEGIN

      info:='WM_NCLBUTTONDBLCLK';

    end;

    WM_NCRBUTTONDOWN:BEGIN

      info:='WM_NCRBUTTONDOWN';

    end;

    WM_NCRBUTTONUP:BEGIN

      info:='WM_NCRBUTTONUP';

    end;



    WM_NCRBUTTONDBLCLK:BEGIN

      info:='WM_NCRBUTTONDBLCLK';

    end;

  end;

  info:=info+','+inttostr(PMouseHookStruct(lp)^.wHitTestCode)+ ','+inttostr(MakeLParam(PMouseHookStruct(lp)^.pt.x,PMouseHookStruct(lp)^.pt.Y));

  if Assigned(myMouseHook.callbackFun) then

    myMouseHook.callbackFun(pchar(info));

  Result := CallNextHookEx(myMouseHook.hook,code,wp,lp);

end;



procedure InstallMouseHook(callbackF:Tcallbackfun);stdcall;

begin

  if not myMouseHook.isrun then

  begin

    {2.设置钩子函数

    setwindowhookEx参数说明

    参数idHook指定建立的监视函数类型。

    参数lpfn指定消息函数,在相应的消息产生后,系统会调用该函数并将消息值传递给该函数供处理。函数的一般形式为:

    Hookproc (code:   Integer;   wparam:   WPARAM;   lparam:   LPARAM):   LRESULT   stdcall;

    其中code为系统指示标记(对应于idHook),wParam和lParam为附加参数,根据不同的消息监视类型而不同。

    只要在程序中建立这样一个函数再通过SetwindowsHookEx函数将它加入到消息监视链中就可以处理消息了。

    }

    myMouseHook.hook:=setwindowshookex(WH_MOUSE,@gethookinfo,HInstance,0);

    myMouseHook.callbackfun:=callbackf;

    myMouseHook.isrun:=not mymousehook.isrun;

  end;

end;



procedure UninstallMouseHook();stdcall;

begin

  if   myMouseHook.isrun   then

  begin

    UnHookWindowsHookEx(mymousehook.hook);

    myMouseHook.callbackfun   :=nil;

    myMouseHook.isrun:=not myMouseHook.isrun;

  end;

end;



Procedure DLLEntryPoint(dwReason:DWord);

begin

  Case dwReason of

    DLL_PROCESS_ATTACH:begin

      myMouseHook.isrun:=false;

    end;

    DLL_PROCESS_DETACH:;

    DLL_THREAD_ATTACH:;

    DLL_THREAD_DETACH:;

  End;

end;



exports

  InstallMouseHook,

  UninstallMouseHook;



begin

  DLLProc := @DLLEntryPoint;

  DLLEntryPoint(DLL_PROCESS_ATTACH);

end.

以上是捕获鼠标消息的全局钩子DLL

使用一个新的线程来模拟发送消息

procedure TPlayThread.Execute;

var

  directive:string;

  i:integer;

  ForgroundForm:TForm;

  procedure ExecuteDir(directive:string);

  var

     tempList:TStringList;

     Wp,Lp:integer;

     wmtype:String;

     focusControl:string;

     duration:Cardinal;

     winCtl:TWinControl;

     tempHandle,focusHandle:THandle;

     classname:String;

     mousPoint:TPOINT;

     procedure findFocus;

     var

       temp:TWinControl;

       finded:Boolean;

     begin

       if ((wmtype='WM_MOUSEMOVE') or (wmtype='WM_NCMouseMove')) then Exit;

       winCtl:=TWinControl(ForgroundForm.FindChildControl(focusControl));

       

       if winCtl<>nil then

       begin

         focusHandle:= winCtl.Handle;

         AttachThreadInput(GetWindowThreadProcessId(ForgroundForm.Handle,nil),Self.ThreadID,True);

         Ferrorinfo:=SysErrorMessage(GetLastError);

         winCtl.SetFocus;

         AttachThreadInput(GetWindowThreadProcessId(ForgroundForm.Handle,nil),Self.ThreadID,False);

         Ferrorinfo:=SysErrorMessage(GetLastError);

         Exit;

       end;

       temp:=nil;

       finded:=False;

       while not finded do

       begin

         GetCursorPos(mousPoint);

         tempHandle := WindowFromPoint(mousPoint);

         if tempHandle =0 then

         begin

          Sleep(0);

          Continue;

         end;

         temp:=FindControl(tempHandle);

         if temp=nil then

         begin

          Sleep(0);

          Continue;

         end;

         if (temp.Name = focusControl) or (classname=temp.ClassName) then

            finded:=True;

       end;

       focusHandle := temp.Handle;

       AttachThreadInput(GetWindowThreadProcessId(ForgroundForm.Handle,nil),Self.ThreadID,True);

       Ferrorinfo:=SysErrorMessage(GetLastError);

       temp.SetFocus;

       AttachThreadInput(GetWindowThreadProcessId(ForgroundForm.Handle,nil),Self.ThreadID,False);

       Ferrorinfo:=SysErrorMessage(GetLastError);

     end;

  begin

    tempList:=TStringList.Create;

    try

      tempList.CommaText:=directive;

      tempList.Delimiter:=',';

      wmtype:=tempList[0];

      focusHandle:=0;

      Wp:=StrToIntDef(tempList[1],0);  //wParam

      Lp:=StrToIntDef(tempList[2],0);  //Lparam

      

      duration:= StrToIntDef(tempList[3],0);

      if (duration=0) and (wmtype='WM_NCMouseMove') then Exit;       //小于线程调度时间片的话就不延时---以免 sleep(0)直接放弃时间进入内核态

      if (wmtype='') or (tempList.Count<6) then Exit;

      focusControl :=tempList[4];

      classname := tempList[5];  



      findFocus;

      //鼠标消息     

      if wmtype='WM_LBUTTONDOWN' then TInputHelper.MouseLButtonDown(focusHandle,Wp,Lp)

      else if wmtype='WM_LBUTTONUP' then  TInputHelper.MouseLButtonUp(focusHandle,Wp,Lp,True)

      else if wmtype='WM_LBUTTONDBLCLK' then TInputHelper.MouseLButtonDbClick(focusHandle,Wp,Lp,True)

      else if wmtype='WM_RBUTTONDOWN' then  TInputHelper.MouseRButtonDown(focusHandle,Wp,Lp,True)

      else if wmtype='WM_RBUTTONUP' then  TInputHelper.MouseRButtonUp(focusHandle,Wp,Lp,True)

      else if wmtype='WM_RBUTTONDBLCLK' then  TInputHelper.MouseRButtonDbClick(focusHandle,Wp,Lp,True)

      else if wmtype='WM_MBUTTONDOWN' then TInputHelper.MouseMButtonDown(focusHandle,Wp,Lp,True)

      else if wmtype='WM_MBUTTONUP' then   TInputHelper.MouseMButtonUp(focusHandle,Wp,Lp,True)

      else if wmtype='WM_MBUTTONDBLCLK' then TInputHelper.MouseMButtonDbClick(focusHandle,Wp,Lp,True)

      else if wmtype='WM_MOUSEMOVE' then  TInputHelper.MouseMove(focusHandle,Wp,Lp,True)

      else if wmtype='WM_MOUSEWHEEL' then TInputHelper.MouseWHEEL(focusHandle,Wp,Lp,True)

      //鼠标非客户区

      else if wmtype='WM_NCMouseMove' then  TInputHelper.MouseNCMouseMove(focusHandle,Wp,Lp,True)

      else if wmtype='WM_NCHITTEST' then  TInputHelper.MouseNCHITTEST(focusHandle,Wp,Lp,True)

      else if wmtype='WM_NCLBUTTONDOWN' then  TInputHelper.MouseNCLBUTTONDOWN(focusHandle,Wp,Lp,True)

      else if wmtype='WM_NCLBUTTONUP' then  TInputHelper.MouseNCLBUTTONUP(focusHandle,Wp,Lp,True)

      else if wmtype='WM_NCLBUTTONDBLCLK' then  TInputHelper.MouseNCLBUTTONDBLCLK(focusHandle,Wp,Lp,True)

      else if wmtype='WM_NCRBUTTONDOWN' then  TInputHelper.MouseNCRBUTTONDOWN(focusHandle,Wp,Lp,True)

      else if wmtype='WM_NCRBUTTONUP' then  TInputHelper.MouseNCRBUTTONUP(focusHandle,Wp,Lp,True)

      else if wmtype='WM_NCRBUTTONDBLCLK' then  TInputHelper.MouseRButtonDbClick(focusHandle,Wp,Lp,True)

      //键盘消息    

      else if wmtype='WM_KEYDOWN' then TInputHelper.KeyDown(focusHandle,Wp,Lp,True)

      else if wmtype='WM_KEYUP' then  TInputHelper.KEYUP(focusHandle,Wp,Lp,True)

      else if wmtype='WM_SYSKEYDOWN' then  TInputHelper.KeySYSKEYDOWN(focusHandle,Wp,Lp,True)

      else if wmtype='WM_SYSKEYUP' then TInputHelper.KeySYSKEYUP(focusHandle,Wp,Lp,True);

      Application.ProcessMessages;

      Sleep(duration);

    finally

      tempList.Free;

    end; 

  end;

begin

  Sleep(1000);

  try

    ForgroundForm :=InputRecord.ForgroundForm;

    for i:= 0 to PosList.Count-1 do

    begin

      directive:=PosList[i];

      ExecuteDir(directive);

    end; 

  finally

    InputRecord.FIsPlay:=False;   

  end;



end;

 

点击这里下载代码

你可能感兴趣的:(windows)