zoukankan      html  css  js  c++  java
  • [转载] 全局键盘钩子(WH_KEYBOARD)

    为了显示效果,在钩子的DLL中我们会获取挂钩函数的窗体句柄,这里的主程序窗体名为"TestMain",通过FindWindow查找。

    KeyBoardHook.dll代码

     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,Windows,Messages,
    15   Classes;
    16 
    17 var
    18   fHook:HHOOK;
    19   //执行挂钩程序的窗体句柄
    20   CallHandle:HWND;
    21 
    22 {$R *.res}
    23 
    24 //回调过程
    25 function HookProc(code:Integer;wParam:WPARAM;lParam:LPARAM):LRESULT;stdcall;
    26 var
    27   processid:Cardinal;
    28 begin
    29   //如果有键盘动作
    30   if code = HC_Action then
    31   begin
    32     //获取注入进程的进程id
    33     processid := GetCurrentProcessId;
    34     //如果CallHandle,则查找TestMain窗体句柄
    35     if CallHandle = 0 then
    36       CallHandle := FindWindow(nil,'TestMain');
    37     //获取按键状态 小于0表示按下,如果不做判断,按键按下或抬起都会执行SendMessage
    38     //下面发送WM_USER+101消息,此消息可以用自定义的消息标识发送
    39     if GetKeyState(wParam) < 0 then
    40       SendMessage(CallHandle,WM_USER+101,wParam,processid);
    41   end
    42   else
    43     //下一个钩子
    44     Result := CallNextHookEx(fHook,code,wParam,lParam);
    45 end;
    46 
    47 procedure SetHook;stdcall;
    48 begin
    49   //挂钩,这里没有做挂钩失败的提示
    50   fHook := SetWindowsHookEx(WH_KEYBOARD,@HookProc,HInstance,0);
    51 end;
    52 
    53 procedure StopHook;stdcall;
    54 begin
    55   //摘钩
    56   if fHook <> 0 then
    57     UnhookWindowsHookEx(fHook);
    58 end;
    59 
    60 exports
    61   SetHook name 'SetHook',
    62   StopHook name 'StopHook';
    63 
    64 begin
    65   //初始CallHandle为0
    66   CallHandle := 0;
    67 end.

    TestKeyBoardHook主程序代码

    {
    此窗体用来执行挂钩,为了方便起见,我们把系统的按键返回到该窗体的Memo组件中进行
    显示,所以在dll中,做了获取主窗体的句柄的工作,以便发消息给主窗体,告诉它是哪个
    按键被按下
    }
    unit TestMain;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls,TlHelp32;
    
    type
      TfrmTestMain = class(TForm)
        Memo1: TMemo;
        btn_SetHook: TButton;
        btn_StopHook: TButton;
        procedure btn_SetHookClick(Sender: TObject);
        procedure btn_StopHookClick(Sender: TObject);
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
      private
        { Private declarations }
        procedure WndProc(var Message: TMessage);override;
      public
        { Public declarations }
      end;
    
    var
      frmTestMain: TfrmTestMain;
    
    implementation
    
    procedure SetHook;stdcall;external 'KeyBoardHook';
    procedure StopHook;stdcall;external 'KeyBoardHook';
    
    {$R *.dfm}
    
    procedure TfrmTestMain.btn_SetHookClick(Sender: TObject);
    begin
      SetHook;
    end;
    
    procedure TfrmTestMain.btn_StopHookClick(Sender: TObject);
    begin
      StopHook;
    end;
    
    procedure TfrmTestMain.WndProc(var Message: TMessage);
    var
      hSnapShot:THandle;
      pEntry:TProcessEntry32;
      find:Boolean;
      proName:string;
    begin
      if Message.Msg = WM_USER+101 then
      begin
        //创建进程快照
        hSnapShot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
        pEntry.dwSize := SizeOf(pEntry);
        find := Process32First(hSnapShot,pEntry);                  
        while find do
        begin
          //取进程名字
          proName := pEntry.szExeFile;
          if pEntry.th32ProcessID = Message.LParam then Break;
          find := Process32Next(hSnapShot,pEntry);
        end;
        Memo1.Lines.Add('进程:' + proName + ',ID:' +IntToStr(Message.LParam)+'按下按键:'+Chr(Message.WParam));
        CloseHandle(hSnapShot);
      end;
      inherited;
    end;
    
    procedure TfrmTestMain.FormClose(Sender: TObject;
      var Action: TCloseAction);
    begin
      StopHook;
    end;
    
    end.

  • 相关阅读:
    极客标签编程小挑战#31:生成注册页面的显示效果
    极客Web前端开发资源大荟萃#017
    知道你们不想撸代码写PPT之可视化页面做一款炫酷的WEB PPT
    使用jQuery图表插件Sparklines来开发一个实用的网站PV(page view)实时监控应用
    javascript专业八级测试答案整理
    使用Raphaël类库实现的超酷动画技能图表
    极客编程小挑战#26:实现日期级联下拉选择框
    gulp初印象
    程序语言,编译?解释?
    发了这嘛多技术文章,今天给大家点福利吧!邻家小美女一枚,想在北京找个工作,大家来看看给出点主意。
  • 原文地址:https://www.cnblogs.com/caohenry999/p/6611912.html
Copyright © 2011-2022 走看看