delphi 全局键盘钩子(WH_KEYBOARD)


本文整理自网络,侵删。

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

 

KeyBoardHook.dll代码

library KeyBoardHook;

{ 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,Windows,Messages,
  Classes;

var
  fHook:HHOOK;
  //执行挂钩程序的窗体句柄
  CallHandle:HWND;

{$R *.res}

//回调过程
function HookProc(code:Integer;wParam:WPARAM;lParam:LPARAM):LRESULT;stdcall;
var
  processid:Cardinal;
begin
  //如果有键盘动作
  if code = HC_Action then
  begin
    //获取注入进程的进程id
    processid := GetCurrentProcessId;
    //如果CallHandle,则查找TestMain窗体句柄
    if CallHandle = 0 then
      CallHandle := FindWindow(nil,'TestMain');
    //获取按键状态 小于0表示按下,如果不做判断,按键按下或抬起都会执行SendMessage
    //下面发送WM_USER+101消息,此消息可以用自定义的消息标识发送
    if GetKeyState(wParam) < 0 then
      SendMessage(CallHandle,WM_USER+101,wParam,processid);
  end
  else
    //下一个钩子
    Result := CallNextHookEx(fHook,code,wParam,lParam);
end;

procedure SetHook;stdcall;
begin
  //挂钩,这里没有做挂钩失败的提示
  fHook := SetWindowsHookEx(WH_KEYBOARD,@HookProc,HInstance,0);
end;

procedure StopHook;stdcall;
begin
  //摘钩
  if fHook <> 0 then
    UnhookWindowsHookEx(fHook);
end;

exports
  SetHook name 'SetHook',
  StopHook name 'StopHook';

begin
  //初始CallHandle为0
  CallHandle := 0;
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.

来源:http://www.cnblogs.com/key-ok/p/3429867.html

相关阅读 >>

Delphi 动态生成进度条窗体

Delphi 获取listview1鼠标所在位置的行名称

Delphi 使用firedac tfdibbackup和tfdibrestore备份和还原firebird

Delphi getvolumeinformation获取硬盘分区信息

Delphi rewrite 以可写方式打开文件

Delphi用api设置定时器

Delphi xe 移动平台 showmodal 范例

github上通过星级评估排名前10的最受欢迎的开源Delphi项目

Delphi 利用51.la统计程序使用量

Delphi串口api函数

更多相关阅读请进入《Delphi》频道 >>



打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...