为了显示效果,在钩子的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://blog.csdn.net/bdmh/article/details/6124127