zoukankan      html  css  js  c++  java
  • 使用钩子函数[2]

    钩子函数虽然不多, 但其参数复杂, 应该从参数入手才能深入进去.

    UnhookWindowsHookEx 只需要 SetWindowsHookEx 返回的钩子句柄作参数, 这个简单;

    先看看 SetWindowsHookEx 的声明:
    SetWindowsHookEx(
      idHook: Integer;   {钩子类型}
      lpfn: TFNHookProc; {函数指针}
      hmod: HINST;       {包含钩子函数的模块(EXE、DLL)的句柄}
      dwThreadId: DWORD  {关联的线程}
    ): HHOOK;
    
    第一个参数非常麻烦, 从后面说:

    参数四 dwThreadId : 在设置全局钩子时这个参数一般是 0, 表示关联所有线程; 本例是线程级的钩子, 所以是
    GetCurrentThreadId.

    参数三 hmod: 是模块实例的句柄, 在 EXE 和 DLL 中都可以用 HInstance 得到当前实例的句柄; 直接用 API 也可以:
    GetModuleHandle(nil).

    参数二 lpfn: 是钩子函数的指针, 用 @ 和 Addr 函数都可以得到函数指针; 这里的关键是那个钩子函数:
    首先不同的钩子类型对应着不同的钩子函数结构, Win32 共有 14 种钩子类型, 这是 详细注释;
    本例用的是键盘钩子, 键盘钩子的回调函数的参数结构在 这里, 我们定义的函数名无所谓, 参数必须按照Windows的规定来.
    还有, 这个回调函数的调用惯例必须是: stdcall; 我们在上例中是先在接口区声明, 如果不要声明直接实现, 也不能忘了这个 stdcall.

    根据以上说明, 做如下修改:
    SetWindowsHookEx 的参数有变通;
    并且取消了钩子函数在接口区的声明, 是直接实现的;
    取消了拦截条件, 现在只要是键盘消息全都拦截.
    unit Unit1;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs;
    
    type
      TForm1 = class(TForm)
        procedure FormCreate(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
      end;
    
    var
      Form1: TForm1;
    
    implementation
    
    {$R *.DFM}
    
    var
      hook: HHOOK; {定义一个钩子句柄}
    
    {现在这个钩子函数没有在接口区声明, 这里必须指定参数调用方式: stdcall}
    function KeyHook(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
    begin
      Beep;
      Result := CallNextHookEx(hook, nCode, wParam, lParam);
    end;
    
    {设置键盘钩子}
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      hook := SetWindowsHookEx(WH_KEYBOARD, Addr(KeyHook), HInstance, GetCurrentThreadId);
    end;
    
    {释放键盘钩子}
    procedure TForm1.FormDestroy(Sender: TObject);
    begin
      UnhookWindowsHookEx(hook);
    end;
    
    end.
    
    钩子函数为什么非得使用 stdcall 调用机制? 因为钩子函数不是被应用程序调用, 而是被系统调用的.
  • 相关阅读:
    linux中编译C语言程序
    plsql 基础教程(二)
    plsql 基础教程(一)
    plsql开发笔记和小结
    表的约束
    一道面试题:说说进程和线程的区别
    HashTable实现原理
    HashMap、Hashtable、HashSet三种hash集合的区别
    Eclipse快捷键大全
    Statement、 PreparedStatement 、CallableStatement 区别和联系
  • 原文地址:https://www.cnblogs.com/del/p/1081763.html
Copyright © 2011-2022 走看看