荔园在线

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

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


发信人: kambi (9s 2 C U), 信区: Program
标  题: win98sign up
发信站: BBS 荔园晨风站 (Mon Feb  8 21:20:19 1999), 站内信件 (WWW POST)

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: 202.96.191.71]


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

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