技术交流,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;
这个钩子的例子,只对自己进程有效,如果我们想全局都有效,就是对别人的进程也有效,那么我们需要将钩子代码写到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以后再讲,这里就大致讲了下钩子如何使用.希望能有点儿帮助.