荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: Peter (小飞侠), 信区: Program
标  题: 使用Windows挂接器
发信站: BBS 荔园晨风站 (Wed Jan 27 17:55:38 1999), 转信


    Windows是一个图形界面消息驱动的OS。用户要想获取系统控制
权,就得截获Windows发给应用程序进程的消息,然后才能做相应处理
。为了截获消息,就得使用挂接器(Hooks)来完成这个工作。
    挂接器(Hooks)使我们能在特定消息的消息流中插入挂接回调函
数,一旦要监视的事件发生,Windows就自动调用这种挂接回调函数,即
挂接器被激活并按我们预先设定的方式对所发生事件进行相应处理。
挂接器有多种类型,如按拦截方式可分为:用于拦截单一任务的消息,
拦截系统基体的消息,或同时拦截单一任务和系统基体的消息的挂接
器。但所有挂接器的定义,安装及拆除总体原理上是一样的。只是所
截获消息的不同,因而挂接回调函数的具体操作不同。

    挂接器机制
    为了跟踪系统中被激活的挂接回调函数,Windows维护了一个链表
集。对于每种挂接器类型,Windows就维护一条激活态挂接回调函数的
链。而对于所有具有同一系统域的回调函数( 同一挂接器类型)Windo
ws使用一个链。

    自定义挂接回调函数
    格式:LRESULT CALLBACK hookcallbackfunction(nCode,wParam,
lParam);
    int nCode;   //挂接器动作代码,nCode<0在Windows 3.1中是不
允许的
    WPARAM wParam;  //挂接器类型和nCode是相互联系的
    LPARAM lParam;  //挂接器类型和lParam是相互联系的
    一般回调函数的框架为:
    LERSULT CALLBACK  函数名(int nCode,WPARAM wParam,LPARAM
LParam)
    {变量定义;
    if (nCode<0) 就调用同一挂接链中的下个挂接器函数;//不对所
截获的消息进行处理
    else
    {对所截获的消息进行相应处理;}
    调用挂接链中的下一个挂接器函数;
    }
    当一个挂接回调函数被Windows调用,也即它所监视的任务发生时
,它传回一个代码———nCode,以告诉回调函数它要求什么动作,它与
传回Windows过程的消息ID值的概念相类似。挂接器类型不同,nCode
也取不同的值,回调函数就可视nCode取值的不同而进行分类处理。另
外,回调函数接收两个参数,这两个参数的意义取决于挂接类型和nCod
e。当回调函数完成后,就向Windows返回一个结果码———lResult,
该码的意义也取决于挂接类型和nCode。
    注意:在挂接器函数中不管是否对所截获消息进行处理,在返回之
前必须调用同一挂接链中的下一个函数,同样被调用的函数也调用下
一个同类函数,除非此链中已没有挂接器函数了。

    安装挂接器
    可以使用SetWindowHookExAPI(int idHook,
    HOOKPROC lpfn,
    HINSTANCE hInstance,
    HTASK hTask)
    函数来安装一个挂接器。最新安装的挂接器加在适当挂接链的顶
部(开始处)。同时利用此函数可以设定挂接器的任务(idHook取不同
的值,挂接器就监视不同的消息)。右挂接器安装成功,则返回挂接器
句柄,否则返回NULL。
表1
    idHook的值和挂接器类型关系表如下:
    调用下一个挂接回调函数
    CallNextHookEx(HHOOK hHook,
    int nCode,
    WPARAM wParam,
    LPARAM lParma)
    它可以在挂接回调函数中调用当前链中的下一个挂接回调函数,
这使得能在同一通知下调用多个挂接回调函数,以便系统能正确选择
挂接器回调函数来对所发生的事件进行处理。若当前链中没有其它回
调函数,则返回0。
    注意:对于同一发生的事件既有任务挂接链,也有系统挂接链,则W
indows调用任务链中的第一个挂接函数。Windows不直接调用系统挂
接链,当Call-NextHookEx()到达任务链的最后一个回调函数时,Windo
ws才将调用系统链中的第一个回调函数。
    拆除挂接器
    当一个挂接器不再需要时,可以通过调用Unhook-WindowsHookEx(
HHOOK hHook)函数将它从挂接链中移去。挂接器可以任何顺序拆除。
若拆除成功,返回TRUE,否则返回FALSE。
    一个挂接器例子
    上面介绍了怎样定义回调函数及怎样安装拆除挂接器。下面就简
单举一实例来说明一下。此例子的功能是检测当前鼠标消息。若用户
单击右键,则将当前激活的应用程序进程终止。
    自定义回调函数代码:
    LRESULT-export CALLBACK RButtonKill(
    int nCode,
    WPARAM wParam,
    LPARAM lParam)
    (LPMOUSEHOOK STRUCT ms;
    if ((wParam==WM-RBUTTONDOWN)||(WParam==WM-NCRBUTTONDOWN)
    (MessageBeep(-1);
    ms=(LPMOUSEHOOK STRUCT)lParam;
    PostMessage(ms->hwnd,WM-QUIT,0,0L);
    //向当前激活的应用程序进程发返回消息
    return(1);
    }
    return (CallNextHookEx(hHook,code,wParam,lParam);
    }
    安装挂接器:
    HHOOK hHook;
    hHook=SetWindowsHookEx(WM-MOUSE,
    (HOOKPROC)GetProAddress(hInstance,"RButtonKill),
    hInstance,NULL);
    拆除挂接器:
    UnhookWindowsHookEx(hHook);
    上面是例子中的一些重要代码。只要编写一个简单的小程序,并
在主窗口过程中安装RB ottonkill挂接器后,它就开始监测系统中所
有鼠标消息,并当检测到单击鼠标右键时,向当前激活的任何应用进程
主窗口过程发WM-QUIT消息,迫使当前应用程序进程退出。
    Hooks和DOS中的中断有类似之处,利用好了,可以大大提高程序的
功能和效率。但要特别注意:挂接回调函数处于消息处理流的中间,而
消息处理流对于Windows性能来说是一个关键的途径。对于具有系统
域的挂接器来说尤其是这样,因为这种挂接器影响所有Windows应用程
序。
    采用措施:
    ·只要有可能就使用任务链而不使用系统链;
    ·只有必要时才加载挂接器,并且尽快使之退出挂接器;
    ·除非对您的程序至关重要,否则不要使用那些会被频繁调用的
挂接器,尤其是WH-CALL WNDPROC型挂接器。

--
※ 来源:.BBS 荔园晨风站 bbs.szu.edu.cn.[FROM: 192.168.1.3]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店