• 使用钩子函数[1]



    目前对钩子的理解:

    譬如我们用鼠标在某个窗口上双击了一次, 或者给某个窗口输入了一个字母 A;
    首先发现这些事件的不是窗口, 而是系统!

    然后系统告诉窗口: 喂! 你让人点了, 并且是连续点了两鼠标, 你准备怎么办?
    或者是系统告诉窗口: 喂! 有人向你家里扔砖头了, 不信你看看, 那块砖头是 A.

    这时窗口的对有些事件会忽略、对有些事件会做出反应:
    譬如, 可能对鼠标单击事件忽略, 窗口想: 你单击我不要紧, 累死你我不负责;
    但一旦谁要双击我, 我会马上行动, 给你点颜色瞧瞧!
    这里窗口准备要采取的行动, 就是我们提前写好的事件.
    用 Windows 的话说, 窗口的事件就是系统发送给窗口的消息; 窗口要采取的行动(事件代码)就是窗口的回调函数.

    但是! 往往隔墙有耳. 系统要通知给窗口的"话"(消息), 可能会被另一个家伙(譬如是一个贼)提前听到!
    有可能这个贼就是专门在这等情报的, 贼知道后, 往往在窗口知道以前就采取了行动!
    并且这个贼对不同的消息会采取不同的行动方案, 它的行动方案一般也是早就准备好的;
    当然这个贼也不是对什么消息都感兴趣, 对不感兴趣的消息也就无须制定相应的行动方案.

    总结: 这个"贼"就是我们要设置的钩子; "贼"的"行动方案"就是钩子函数, 或者叫钩子的回调函数.

    钩子分两种, 一种是系统级的全局钩子; 一种是线程级的钩子.
    全局钩子函数需要定义在 DLL 中, 从线程级的钩子开始比较简单.

    其实钩子函数就三个:
    设置钩子: SetWindowsHookEx
    释放钩子: UnhookWindowsHookEx
    继续钩子: CallNextHookEx
    在线程级的钩子中经常用到 GetCurrentThreadID 函数来获取当前线程的 ID.

    下面例子中设定了一个线程级的键盘钩子, 专门拦截字母 A.
    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;
    
    {声明键盘钩子回调函数; 其参数传递方式要用 API 的 stdcall}
    function KeyHook(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
    
    var
      Form1: TForm1;
    
    implementation
    
    {$R *.DFM}
    
    var
      hook: HHOOK; {定义一个钩子句柄}
    
    {实现键盘钩子回调函数}
    function KeyHook(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT;
    begin
      if (wParam = 65) then Beep; {每拦截到字母 A 会发声}
      Result := CallNextHookEx(hook, nCode, wParam, lParam);
    end;
    
    {设置键盘钩子}
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      hook := SetWindowsHookEx(WH_KEYBOARD, @KeyHook, 0, GetCurrentThreadID);
    end;
    
    {释放键盘钩子}
    procedure TForm1.FormDestroy(Sender: TObject);
    begin
      UnhookWindowsHookEx(hook);
    end;
    
    end.
    
    尽管这个例子已经很简单了, 但还不足以让人明白彻底; 下面还得从更简单的开始.

  • 相关阅读:
    P1662 数7
    P3645 [APIO2015]雅加达的摩天楼
    P3396 哈希冲突
    P7479 至曾是英雄的您
    P7480 Reboot from Blue
    Apache Commons Collections
    ESP8266 WIFI杀手
    ESP8266 固件升级
    ESP8266 MicroPython安装与使用
    Window 安装子系统
  • 原文地址:https://www.cnblogs.com/del/p/1080825.html
Copyright © 2020-2023  润新知