读书 - Delphi下深入Windows核心编程 第二天

技术交流,DH讲解.

今天进入这书第二章 钩子(HOOK).
先说说钩子是什么?
钩子其实就在你环境中加上一层过滤,在特殊情况下就触发钩子回调函数.
比如说我们安装了全局的键盘钩子,那么当我们按动键盘上面的键的时候,钩子的回调函数就会触发.
我们也能看到本来是直来直往的,结果现在中间安装了一层过滤,系统的效率肯定会有所下降的.
要了解,我们只需要知道3个函数:
1 上钩函数:

function SetWindowsHookEx(
	idHook: Integer;//钩子的类型 
	lpfn: TFNHookProc; //回调函数指针
	hmod: HINST; //一般为0或者Instance
	dwThreadId: DWORD//全局钩子就为0,不然就为指定进程id
		): HHOOK; stdcall;//成功就返回一个值,不成功就为0

其中钩子类型有:

{$EXTERNALSYM WH_MIN}
  WH_MIN = -1;
  {$EXTERNALSYM WH_MSGFILTER}
  WH_MSGFILTER = -1;
  {$EXTERNALSYM WH_JOURNALRECORD}
  WH_JOURNALRECORD = 0;
  {$EXTERNALSYM WH_JOURNALPLAYBACK}
  WH_JOURNALPLAYBACK = 1;
  {$EXTERNALSYM WH_KEYBOARD}
  WH_KEYBOARD = 2;
  {$EXTERNALSYM WH_GETMESSAGE}
  WH_GETMESSAGE = 3;
  {$EXTERNALSYM WH_CALLWNDPROC}
  WH_CALLWNDPROC = 4;
  {$EXTERNALSYM WH_CBT}
  WH_CBT = 5;
  {$EXTERNALSYM WH_SYSMSGFILTER}
  WH_SYSMSGFILTER = 6;
  {$EXTERNALSYM WH_MOUSE}
  WH_MOUSE = 7;
  {$EXTERNALSYM WH_HARDWARE}
  WH_HARDWARE = 8;
  {$EXTERNALSYM WH_DEBUG}
  WH_DEBUG = 9;
  {$EXTERNALSYM WH_SHELL}
  WH_SHELL = 10;
  {$EXTERNALSYM WH_FOREGROUNDIDLE}
  WH_FOREGROUNDIDLE = 11;
  {$EXTERNALSYM WH_CALLWNDPROCRET}
  WH_CALLWNDPROCRET = 12;
  {$EXTERNALSYM WH_KEYBOARD_LL}
  WH_KEYBOARD_LL = 13;
  {$EXTERNALSYM WH_MOUSE_LL}
  WH_MOUSE_LL = 14;
  {$EXTERNALSYM WH_MAX}
  WH_MAX = 14;
  {$EXTERNALSYM WH_MINHOOK}
  WH_MINHOOK = WH_MIN;
  {$EXTERNALSYM WH_MAXHOOK}
  WH_MAXHOOK = WH_MAX;

具体作用基本上就看名字就知道,个别的我也不知道,具体的大家看MSDN吧.这个是个葵花宝典.
2 卸钩函数:

function UnhookWindowsHookEx(
	hhk: HHOOK//上钩函数返回的句柄
		): BOOL; stdcall;

3 具体的钩子回调函数:

TFNHookProc = function (code: Integer; wparam: WPARAM; lparam: LPARAM): LRESULT stdcall;

好的说了这么多,看例子:

Var
  H: HHOOK;

Function MyKeyBoardHookProc(Code: Integer; Wparam: WPARAM;
  Lparam: LPARAM): LRESULT Stdcall;
Begin
  If Code = HC_ACTION Then
  Begin
    // wparam是virtal code
    // lparam要分字节
    ShowMessage(Format('点击%D键%D次', [Wparam, Lparam And $0000FFFF]));
  End;
  // 一定要记得调用下一个钩子,因为我们要知道可能这个东西不只是你要处理,别人也要处理,
  // 如果你处理,就不往下传了,我也米有办法...算你BT
  Result := CallNextHookEx(H, Code, Wparam, Lparam);
End;

Procedure TForm2.Button1Click(Sender: TObject);
Begin
  H := SetWindowsHookEx(WH_KEYBOARD, MyKeyBoardHookProc, 0, GetCurrentThreadId);
End;

Procedure TForm2.Button2Click(Sender: TObject);
Begin
  UnhookWindowsHookEx(H)
End;


image
这个钩子的例子,只对自己进程有效,如果我们想全局都有效,就是对别人的进程也有效,那么我们需要将钩子代码写到Dll里面去.

接下来就演示全局钩子吧.

Var
  H: HHOOK;
  ExeHandle: Cardinal; // 这个handle一定能要用内存映射出来,因为全局键盘钩子话,
  // 只要程序一按键,dll就会加载到这个进程里面了,所以就形成多进程情况,这里我就不弄了

Function MyKeyBoardProc(Code: Integer; Wparam: WPARAM;
  Lparam: LPARAM): LRESULT Stdcall;
Begin
  If Code = HC_ACTION Then
    PostMessage(ExeHandle, WM_HOTKEY, Wparam, Lparam); // 这里偷懒了,直接转发出去
  Result := CallNextHookEx(H, Code, Wparam, Lparam)
End;

Function HookOn(AHandle: Cardinal): Boolean; Export; // 导出它
Begin
  ExeHandle := AHandle;
  H := SetWindowsHookEx(WH_KEYBOARD, MyKeyBoardProc, HInstance, 0);
  // 最后一个参数一定是0
  Result := H <> 0; // 判断是否成功
End;

Function HookOff(): Boolean;export;
Begin
  Result := UnhookWindowsHookEx(H)
End;

其他的api hook以后再讲,这里就大致讲了下钩子如何使用.希望能有点儿帮助.

posted @ 2010-01-21 22:56  HuangJacky  阅读(1116)  评论(0编辑  收藏  举报
AdminLogin