技术交流,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以后再讲,这里就大致讲了下钩子如何使用.希望能有点儿帮助.
|
请发表评论