《2022年高中信息技术教学论文消息钩子函数入门篇.docx》由会员分享,可在线阅读,更多相关《2022年高中信息技术教学论文消息钩子函数入门篇.docx(11页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、精选学习资料 - - - - - - - - - 消息钩子函数入门篇Windows 系统是建立在大事驱动的机制上的,说穿了就是整个系统都是通过消息的传递来 实现的;而钩子是 Windows系统中特别重要的系统接口,用它可以截获并处理送给其他应 用程序的消息,来完成一般应用程序难以实现的功能;钩子可以监视系统或进程中的各种大事消息,截获发往目标窗口的消息并进行处理;这样,我们就可以在系统中安装自定义 的钩子,监视系统中特定大事的发生,完成特定的功能,比如截获键盘、鼠标的输入,屏幕取词,日志监视等等;可见,利用钩子可以实现很多特殊而有用的功能;因此,对于高 级编程人员来说,把握钩子的编程方法是很有
2、必要的;钩子的类型一 按大事分类,有如下的几种常用类型(1) 键盘钩子和低级键盘钩子可以监视各种键盘消息;(2) 鼠标钩子和低级鼠标钩子可以监视各种鼠标消息;(3) 外壳钩子可以监视各种Shell大事消息;比如启动和关闭应用程序;(4) 日志钩子可以记录从系统消息队列中取出的各种大事消息;(5) 窗口过程钩子监视全部从系统消息队列发往目标窗口的消息;此外,仍有一些特定大事的钩子供应应我们使用,不一一列举;下面描述常用的 Hook类型:1、WH_CALLWNDPROC 和 WH_CALLWNDPROCRET Hooks WH_CALLWNDPROC 和 WH_CALLWNDPROCRET Hoo
3、ks 使你可以监视发送到窗口过程的消息;系统在消息发送到接收窗口过程之前调用WH_CALLWNDPROC Hook 子程,并且在窗口过程处理完消息之后调用 WH_CALLWNDPRO CRET Hook子程; WH_CALLWNDPROCRET Hook 传递指针到 CWPRETSTRUCT 结构,再传递到 Hook 子程; CWPRETSTRUCT 结构包含了来自处理消息的窗口过程的返回值,同样也包括了与这个消息关联的消息参数;2、WH_CBT Hook 在以下大事之前,系统都会调用WH_CBT Hook子程,这些大事包括:1. 激活,建立,销毁,最小化,最大化,移动,转变尺寸等窗口大事;2
4、. 完成系统指令;3. 来自系统消息队列中的移动鼠标,键盘大事;4. 设置输入焦点大事;5. 同步系统消息队列大事;Hook 子程的返回值确定系统是否答应或者防止这些操作中的一个;3、WH_DEBUG Hook 在系统调用系统中与其他 Hook 关联的 Hook 子程之前,系统会调用 WH_DEBUG Hook子程;你可以使用这个 Hook来打算是否答应系统调用与其他 Hook关联的 Hook 子程;4、WH_FOREGROUNDIDLE Hook 当应用程序的前台线程处于闲暇状态时,可以使用WH_FOREGROUNDIDLE Hook 执行低优先级的任务;当应用程序的前台线程大致要变成闲暇状
5、态时,系统就会调用 WH_FOREGROUNDIDLE Hook 子程;5、WH_GETMESSAGE Hook 名师归纳总结 - - - - - - -第 1 页,共 6 页精选学习资料 - - - - - - - - - 应用程序使用WH_GETMESSAGE Hook 来监视从 GetMessage or PeekMessage函数返回的消息;你可以使用 WH_GETMESSAGE Hook 去监视鼠标和键盘输入,以及其他发送到消息队列中的消息;6、WH_JOURNALPLAYBACK Hook WH_JOURNALPLAYBACK Hook 使应用程序可以插入消息到系统消息队列;可以使
6、用这个 Hook回放通过使用 WH_JOURNALRECORD Hook 记录下来的连续的鼠标和键盘大事;只要 WH_JOURNALPLAYBACK Hook已经安装,正常的鼠标和键盘大事就是无效的;WH_JOURNALPLAYBACK Hook 是全局 Hook,它不能象线程特定 Hook 一样使用; WH_JOURNALPLAYBACK Hook 返回超时值,这个值告知系统在处理来自回放Hook 当前消息之前需要等待多长时间(毫秒);这就使 Hook 可以掌握实时大事的回放;WH_JOURNALPLAYBACK 是 system-wide local hooks,它們不會被注射到任何行程位
7、址空間;(估量按键精灵是用这个 hook 做的)7、WH_JOURNALRECORD Hook WH_JOURNALRECORD Hook 用来监视和记录输入大事;典型的,可以使用这个 Hook 记录连续的鼠标和键盘大事,然后通过使用WH_JOURNALPLAYBACK Hook 来回放; WH_JOURNALRECORD Hook 是全局 Hook,它不能象线程特定 Hook 一样使用; WH_JOURNALRECORD 是 system-wide local hooks,它們不會被注射到任何行程位址空間;8、WH_KEYBOARD Hook 在应用程序中,WH_KEYBOARD Hook
8、用来监视 WM_KEYDOWN and WM_KEYUP 消息,这些消息通过 GetMessage or PeekMessage function 返回;可以使用这个 Hook 来监视输入到消息队列中的键盘消息;9、WH_KEYBOARD_LL Hook WH_KEYBOARD_LL Hook 监视输入到线程消息队列中的键盘消息;10、 WH_MOUSE Hook WH_MOUSE Hook 监视从 GetMessage 或者 PeekMessage 函数返回的鼠标消息;使用这个 Hook 监视输入到消息队列中的鼠标消息;11、 WH_MOUSE_LL Hook WH_MOUSE_LL Hoo
9、k 监视输入到线程消息队列中的鼠标消息;12、 WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks使我们可以监视菜单,滚动条,消息框,对话框消息并且发觉用户使用 ALT+TAB or ALT+ESC 组合键切换窗口;WH_MSGFILTER Hook只能监视传递到菜单,滚动条,消息框的消息,以及传递到通过安装了Hook子程的应用程序建立的对话框的消息;WH_SYSMSGFILTER Hook 监视全部应用程序消息;WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks使我们可以在模
10、式循环期间过滤消息,这等价于在主消息循环中过滤消息;通过调用CallMsgFilter function可以直接的调用WH_MSGFILTER Hook;通过使用这个函数,应用程序能够在模式循环期间使用相同的代码去过滤消息,犹如在主消息循环里一样;13、 WH_SHELL Hook 外壳应用程序可以使用 WH_SHELL Hook去接收重要的通知;当外壳应用程序是激活的并且当顶层窗口建立或者销毁时,系统调用 WH_SHELL Hook子程;WH_SHELL 共有钟情況:1. 只要有个 top-level、unowned 窗口被产生、起作用、或是被摧残;2. 当 Taskbar 需要重画某个按钮
11、;名师归纳总结 - - - - - - -第 2 页,共 6 页精选学习资料 - - - - - - - - - 3. 当系统需要显示关于 Taskbar 的一个程序的最小化形式;4. 当目前的键盘布局状态转变;5. 当使用者按 Ctrl+Esc 去执行 Task Manager (或相同级别的程序);WH_SHELL 依据惯例,外壳应用程序都不接收 WH_SHELL消息;所以,在应用程序能够接收 消息之前,应用程序必需调用 SystemParametersInfo function 注册它自己;以上是 13 种常用的 hook 类型!二 按使用范畴分类,主要有线程钩子和系统钩子(1) 线程钩
12、子监视指定线程的大事消息;(2) 系统钩子监视系统中的全部线程的大事消息;由于系统钩子会影响系统中全部 的应用程序,所以钩子函数必需放在独立的动态链接库 DLL 中;这是系统钩子和线程钩子很大的不同之处;几点需要说明的地方:(1) 假如对于同一大事(如鼠标消息)既安装了线程钩子又安装了系统钩子,那么 系统会自动先调用线程钩子,然后调用系统钩子;(2) 对同一大事消息可安装多个钩子处理过程,这些钩子处理过程形成了钩子链;当前钩子处理终止后应把钩子信息传递给下一个钩子函数;而且最近安装的钩子放在链的 开头,而最早安装的钩子放在最终,也就是后加入的先获得掌握权;(3) 钩子特殊是系统钩子会消耗消息处
13、理时间,降低系统性能;只有在必要的时候 才安装钩子,在使用完毕后要准时卸载;编写钩子程序 编写钩子程序的步骤分为三步:定义钩子函数、安装钩子和卸载钩子;1定义钩子函数 钩子函数是一种特殊的回调函数;钩子监视的特定大事发生后,系统会调用钩子函数 进行处理;不同大事的钩子函数的形式是各不相同的;下面以鼠标钩子函数举例说明钩子函数的原型:LRESULT CALLBACK HookProcint nCode ,WPARAM wParam,LPARAM lParam 参数 wParam和 lParam 包含所钩消息的信息,比如鼠标位置、状态,键盘按键等;nCode 包含有关消息本身的信息,比如是否从消息
14、队列中移出;我们先在钩子函数中实现自定义的功能,然后调用函数 CallNextHookEx. 把钩子信息传递 给钩子链的下一个钩子函数;CallNextHookEx. 的原型如下:LRESULT CallNextHookEx HHOOK hhk, int nCode, WPARAM wParam, LPARAM lParam 参数 hhk 是钩子句柄; nCode、wParam和 lParam 是钩子函数;当然也可以通过直接返回 TRUE来丢弃该消息,就阻挡了该消息的传递;2安装钩子在程序初始化的时候,调用函数SetWindowsHookEx 安装钩子;其函数原型为:HHOOK SetWind
15、owsHookEx int idHook,HOOKPROC lpfn, INSTANCE hMod,DWORD dwThreadId 参数 idHook 表示钩子类型,它是和钩子函数类型一一对应的;比如,WH_KEYBOARD 表示安装的是键盘钩子,WH_MOUSE 表示是鼠标钩子等等;Lpfn 是钩子函数的地址;HMod是钩子函数所在的实例的句柄;对于线程钩子,该参数为 该参数为钩子函数所在的 DLL句柄;NULL;对于系统钩子,名师归纳总结 - - - - - - -第 3 页,共 6 页精选学习资料 - - - - - - - - - dwThreadId 指定钩子所监视的线程的线程号;
16、对于全局钩子,该参数为NULL;SetWindowsHookEx 返回所安装的钩子句柄;3卸载钩子当不再使用钩子时,必需准时卸载;简洁地调用函数 HOOK hhk即可; BOOL UnhookWindowsHookEx H值得留意的是线程钩子和系统钩子的钩子函数的位置有很大的差别;线程钩子一般在当前 线程或者当前线程派生的线程内,而系统钩子必需放在独立的动态链接库中,实现起来要 麻烦一些;线程钩子的编程实例:依据上面介绍的方法实现一个线程级的鼠标钩子;钩子跟踪当前窗口鼠标移动的位置 变化信息;并输出到窗口;1 在 VC 6.0 中利用 MFC APPWizard( EXE)生成一个不使用文档/
17、 视结构的单文档应用mousehook;打开 childview.cpp 文件,加入全局变量:HHOOK hHook;/ 鼠标钩子句柄 CPoint point;/ 鼠标位置信息 CChildView pView;/ 鼠标钩子函数用到的输出窗口指针在 CChildView:OnPaint 添加如下代码:CPaintDC dcthis;char str256;sprintfstr,“ x= d,y= d,point.x,point.y / 构造字符串 dc.TextOut0,0,str; / 显示字符串2childview.cpp 文件中定义全局的鼠标钩子函数;LRESULT CALLBACK
18、MouseProc int nCode, WPARAM wParam, LPARAM lParam / 是鼠标移动消息 ifwParam=WM_MOUSEMOVE|wParam =WM_NCMOUSEMOVE point=MOUSEHOOKSTRUCT lParam pt ;/ 取鼠标信息pViewInvalidate; /窗口重画 return CallNextHookExhHook,nCode,wParam,lParam;/ 传递钩子信息 名师归纳总结 - - - - - - -第 4 页,共 6 页精选学习资料 - - - - - - - - - 3CChildView 类的构造函数中安
19、装钩子;CChildView:CChildView pView=this ;/ 获得输出窗口指针 hHook=SetWindowsHookExWH_MOUSE,MouseProc,0,GetCurrentThreadId; 4CChildView 类的析构函数中卸载钩子;CChildView:CChildView ifhHook UnhookWindowsHookExhHook; 系统钩子的编程实例:由于系统钩子要用到dll ,所以先介绍下win32 dll的特点:Win32 DLL 与 Win16 DLL 有很大的区分,这主要是由操作系统的设计思想打算的;一方面,在 Win16 DLL 中程
20、序入口点函数和出口点函数(LibMain 和 WEP)是分别实现的;而在Win32 DLL 中却由同一函数 DLLMain 来实现;无论何时,当一个进程或线程载入和卸载 DLL时,都要调用该函数,它的原型是 BOOL WINAPI DllMain HINSTANCE hinstDLL,DWORD fdwReason, LPVOID lpvReserved;,其中,第一个参数表示 DLL 的实例句柄;第三个参数系统保留;这里主要介绍一下其次个参数,它有四个可能的值: DLL_PROCESS_ATTACH(进程载入),DLL_THREAD_ATTACH(线程载入),DLL_THREAD_DETAC
21、H(线程卸载),DLL_PROCESS_DETACH(进程卸载),在 DLLMain 函数中可以对传递进来的这个参数的值进行判别,并依据不同的参数值对DLL进行必要的初始化或清理工作;举个例子来说,当有一个进程载入一个 DLL 时,系统分派给 DLL的其次个参数为 DLL_PROCESS_ATTACH,这时,你可以依据这个参数初始化特定的数据;另一方面,在 Win16 环境下,全部应用程序都在同一地址空间;而在Win32 环境下,全部应用程序都有自己的私有空间,每个进程的空间都是相互独立的,这削减了应用程序间的相互影响,但同时也增加了编程的难度;大家知道,在Win16 环境中, DLL的全局数
22、据对每个载入它的进程来说都是相同的;而在Win32 环境中,情形却发生了变化,当进程在载入DLL 时,系统自动把DLL地址映射到该进程的私有空间,而且也复制该DLL 的全局数据的一份拷贝到该进程空间,也就是说每个进程所拥有的相同的 DLL的全局数据其值却并不肯定是相同的;因此,在 Win32 环境下要想在多个进程中共享数据,就必需进行必要的设置;亦即把这些需要共享的数据分别出来,放置在一个独立的数据段里,并把该段的属性设置为共享;在 VC6中有三种形式的 MFC DLL(在该 DLL 中可以使用和继承已有的 MFC类 可供挑选,即Regular statically linked to MFC
23、 DLL(标准静态链接 MFC DLL)和 Regular using the shared MFC DLL (标准动态链接MFC DLL)以及 Extension MFC DLL (扩展 MFC DLL);名师归纳总结 第一种 DLL的特点是,在编译时把使用的MFC代码加入到DLL中,因此,在使用该程序时第 5 页,共 6 页不需要其他MFC动态链接类库的存在,但占用磁盘空间比较大;其次种DLL 的特点是,在运行时,动态链接到MFC类库,因此削减了空间的占用,但是在运行时却依靠于MFC动态链接类库;这两种DLL既可以被 MFC程序使用也可以被Win32 程序使用;第三种DLL 的特点类似于其次种,做为MFC类库的扩展,只能被MFC程序使用;- - - - - - -精选学习资料 - - - - - - - - - 名师归纳总结 - - - - - - -第 6 页,共 6 页