• DELPHI使用键盘钩子


    小读了一下《Delphi下深入Windows核心编程》感觉里面的东西写得还算可以,至少有学到东西

    于是整理了一下书中的代码,并加上注注释发上来

    首先是最重要的键盘钩子使用的DLL:

    unit UnitDll;
    
    interface
    
    uses Windows;
    
    const BUFFER_SIZE = 16 * 1024; // 文件映射到内存的大小
    const HOOK_MEM_FILENAME = 'MEM_FILE'; // 映像文件名
    const HOOK_MUTEX_NAME = 'MUTEX_NAME'; // 互斥名
    
    type
      // 共享结构
      TShared = record
        Keys: array[0..BUFFER_SIZE] of Char;
        KeyCount: Integer;
      end;
      // 共享结构指针
      PShared = ^TShared;
    
    var
      MemFile, HookMutex: THandle;  // 文件句柄和互斥句柄
      hOldKeyHook: HHook; // 钩子变量
      Shared: PShared; // 共享变量
    
    implementation
    
    // 重要:键盘钩子回调
    function KeyHookProc(iCode: Integer; wParam: WPARAM;
      lParam: LPARAM): LRESULT; stdcall; export;
    const
      KeyPressMask = $80000000;
    begin
      if iCode < 0 then
        Result := CallNextHookEx(hOldKeyHook, iCode, wParam, lParam)
      else
      begin
        if ((lParam and KeyPressMask) = 0) then
        begin
          // 键盘消息捕获
          Shared^.Keys[Shared^.KeyCount] := Char(wParam and $00FF);
          Inc(Shared^.KeyCount);
          // 超出内存限定大小则重置
          if Shared^.KeyCount >= BUFFER_SIZE - 1 then
            Shared^.KeyCount := 0;
        end;
        result:=0;
      end;
    end;
    
    // 安装钩子
    function EnableKeyHook: BOOL; export;     
    begin
      Shared^.KeyCount := 0;
      if hOldKeyHook = 0 then
      begin
        // 设置钩子过滤
        {WH_KEYBOARD: 安装的是键盘钩子 KeyHookProc: 消息回调, HInstance: 回调函数实例 线程ID}
        hOldKeyHook := SetWindowsHookEx(WH_KEYBOARD, KeyHookProc, HInstance, 0);
      end;
      Result := (hOldKeyHook <> 0);
    end;
    
    {撤消钩子过滤函数}
    function DisableKeyHook: BOOL; export;
    begin
      if hOldKeyHook <> 0 then
      begin
        UnHookWindowsHookEx(hOldKeyHook);
        hOldKeyHook := 0;
        Shared^.KeyCount := 0;
      end;
      Result := (hOldKeyHook = 0);
    end;
    
    
    // 得到获得多少按键
    function GetKeyCount: Integer; export;
    begin
      Result := Shared^.KeyCount;
    end;
    
    // 得到第I个按键
    function GetKey(index: Integer): Char; export;
    begin
      Result := Shared^.Keys[index];
    end;
    
    // 清空按键
    procedure ClearKeyString; export;
    begin
      Shared^.KeyCount := 0;
    end;
    
    // 导出函数列表
    exports
      EnableKeyHook,
      DisableKeyHook,
      GetKeyCount,
      ClearKeyString,
      GetKey;
    
    initialization
      // 创建互斥变量,DLL只能有一个进程可以使用
      HookMutex := CreateMutex(nil, True, HOOK_MUTEX_NAME);
      // 打开文件映像
      MemFile := OpenFileMapping(FILE_MAP_WRITE, False, HOOK_MEM_FILENAME);
      // 如果不存在该文件映像则创建
      if MemFile = 0 then
        MemFile := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, SizeOf(TShared), HOOK_MEM_FILENAME);
      // 文件映射内存
      Shared := MapViewOfFile(MemFile, File_MAP_WRITE, 0, 0, 0);
      // 释放互斥变量
      ReleaseMutex(HookMutex);
      // 关闭互斥句柄
      CloseHandle(HookMutex);
    
    finalization
      // 撤消钩子过滤
      if hOldKeyHook <> 0 then
        DisableKeyHook;
      // 释放映射
      UnMapViewOfFile(Shared);
      // 关闭映像文件
      CloseHandle(MemFile);
    end.

    这个看懂了之后就可以直接写个CLIENT调用了

    unit Unit2;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      StdCtrls, ExtCtrls;
    
    type
      TForm1 = class(TForm)
        Memo1: TMemo;
        bSetHook: TButton;
        bCancelHook: TButton;
        bReadKeys: TButton;
        bClearKeys: TButton;
        Panel2: TPanel;
        procedure bSetHookClick(Sender: TObject);
        procedure bCancelHookClick(Sender: TObject);
        procedure bReadKeysClick(Sender: TObject);
        procedure bClearKeysClick(Sender: TObject);
      end;
    
    var
      Form1: TForm1;
    
    
    implementation
    
    {$R *.DFM}
    function EnableKeyHook: BOOL; external 'KEYHOOK.DLL';
    function DisableKeyHook: BOOL; external 'KEYHOOK.DLL';
    function GetKeyCount: Integer; external 'KEYHOOK.DLL';
    function GetKey(idx: Integer): Char; external 'KEYHOOK.DLL';
    procedure ClearKeyString; external 'KEYHOOK.DLL';
    
    procedure TForm1.bSetHookClick(Sender: TObject);
    begin
      EnableKeyHook;
      bSetHook.Enabled := False;
      bCancelHook.Enabled := True;
      bReadKeys.Enabled := True;
      bClearKeys.Enabled := True;
      Panel2.Caption := ' 键盘钩子已经设置';
    end;
    
    procedure TForm1.bCancelHookClick(Sender: TObject);
    begin
      DisableKeyHook;
      bSetHook.Enabled := True;
      bCancelHook.Enabled := False;
      bReadKeys.Enabled := False;
      bClearKeys.Enabled := False;
      Panel2.Caption := ' 键盘钩子没有设置';
    end;
    
    procedure TForm1.bReadKeysClick(Sender: TObject);
    var
       i: Integer;
    begin
      Memo1.Lines.Clear;{在Memo1中显示击键历史记录}
      for i := 0 to GetKeyCount - 1 do
        Memo1.Text := Memo1.Text + GetKey(i);
    
    end;
    
    procedure TForm1.bClearKeysClick(Sender: TObject);
    begin
      Memo1.Clear;
      ClearKeyString;
    end;
    
    end.
  • 相关阅读:
    MySQL Sandbox安装使用
    主从复制延时判断
    Carthage
    QCon 2015 阅读笔记
    QCon 2015 阅读笔记
    Scrum&Kanban在移动开发团队的实践 (一)
    移动开发-第三方聊天服务
    开通博客
    spark的若干问题
    hadoop2.2.0安装需要注意的事情
  • 原文地址:https://www.cnblogs.com/MaxWoods/p/3137117.html
Copyright © 2020-2023  润新知