八宝书库 > 文学其他电子书 > VC语言6.0程序设计从入门到精通 >

第62部分

VC语言6.0程序设计从入门到精通-第62部分

小说: VC语言6.0程序设计从入门到精通 字数: 每页4000字

按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!




WH_JOURNALPLAYBACK 是 system…wide local hooks,它们不会被映射到任何进程的地址空 

间中。  



    (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 用来监视 WM_KEYDOWN 和 WM_KEYUP 消 

息,这些消息通过 GetMessage 或 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 Hook 监视输入到线程消息队列中的鼠标消息。  



 ·272 ·  


…………………………………………………………Page 284……………………………………………………………

                                                     第 10 章    动态链接库  



   (12)WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks  

   WH_MSGFILTER 和 WH_SYSMSGFILTER  Hooks 可以监视菜单、滚动条、消息框、对 

话框消息并且发现用户使用  ALT+TAB  或者  ALT+ESC  组合键切换窗口。WH_MSGFILTER  

Hook 只能监视传递到菜单、滚动条、消息框的消息,以及传递到通过安装了 Hook 子程的应 

用 程 序 建 立 的 对 话 框 的 消 息 。 WH_SYSMSGFILTER   Hook 监 视 所 有 应 用 程 序 消 息 。 

WH_MSGFILTER 和 WH_SYSMSGFILTER  Hooks 可以在模式循环期间过滤消息,这等价于 

在主消息循环中过滤消息。通过调用 CallMsgFilter  function 可以直接调用 WH_MSGFILTER  

Hook 。通过使用这个函数,应用程序能够在模式循环期间使用相同的代码去过滤消息,如同 

在主消息循环里一样。  



   (13)WH_SHELL Hook  

   外壳应用程序可以使用 WH_SHELL Hook 去接收重要的通知。当外壳应用程序为激活状 

态并且当顶层窗口建立或者销毁时,系统调用 WH_SHELL  Hook 子程。WH_SHELL 共有 5 

种情況:  

   o  只要有 top…level 、unowned 窗口被产生、起作用、或是被摧毁;    

   o  当 Taskbar 需要重画某个按钮;    

   o  当系统需要显示关于 Taskbar 的一个程序的最小化形式;    

   o  当目前的键盘布局状态改变;    

   o  当使用者按 Ctrl+Esc 去执行 Task Manager (或相同级别的程序)。  

   按照惯例,外壳应用程序都不接收             WH_SHELL  消息。所以在应用程序能够接收 

WH_SHELL 消息之前,应用程序必须调用 SystemParametersInfo function 注册它自己。  



   2 .按使用范围分类  



   按使用范围分类,主要有线程钩子和系统钩子。线程钩子监视指定线程的事件消息,系 

统钩子监视系统中的所有线程的事件消息。因为系统钩子会影响系统中所有的应用程序,所 

                              DLL )中。  

以钩子函数必须放在独立的动态链接库( 

   o  如果对于同一事件(如鼠标消息)既安装了线程钩子又安装了系统钩子,那么系统会 

                                         

     自动先调用线程钩子,然后调用系统钩子。 

   o  对同一事件消息可安装多个钩子处理过程,这些钩子处理过程形成了钩子链。当前钩 

     子处理结束后应把钩子信息传递给下一个钩子函数。而且最近安装的钩子放在链的开 

     始,而最早安装的钩子放在最后,也就是后加入的先获得控制权。    

   o  钩子特别是系统钩子会消耗消息处理时间,降低系统性能。只有在必要的时候才安装 

     钩子,在使用完毕后要及时卸载。  



10。7。2    使用钩子函数  



   使用钩子函数的程序的步骤分为定义钩子函数、安装钩子和卸载钩子这 3 步。下面详细 

介绍这 3 个过程。  



                                                              ·273 ·  


…………………………………………………………Page 285……………………………………………………………

Visual C++ 6。0 程序设计从入门到精通  



    1.定义钩子函数  



   钩子函数是一种特殊的回调函数 。钩子监视的特定事件发生后,系统会调用钩子函数进 

行处理。不同事件的钩子函数的形式是各不相同的。下面以鼠标钩子函数举例说明钩子函数 

的原型:    



   LRESULT CALLBACK HookProc(int nCode ;WPARAM wParam;LPARAM lParam)  



   参数 wParam 和  lParam 包含所钩消息的信息,比如鼠标位置/状态、键盘按键等。nCode 

包含有关消息本身的信息,比如是否从消息队列中移出。    

   先在钩子函数中实现自定义的功能,然后调用函数 CallNextHookEx。把钩子信息传递给钩 

子链的下一个钩子函数。CallNextHookEx。 的原型如下:    



   LRESULT CallNextHookEx(HHOOK hhk; int nCode; WPARAM wParam; LPARAM lParam)  



   参数  hhk 是钩子句柄。nCode 、wParam 和 lParam  是钩子函数。    

   也可以通过直接返回 TRUE 来丢弃该消息,阻止该消息的传递。  



   2 .安装钩子  



   在程序初始化的时候,调用函数 SetWindowsHookEx 安装钩子。其函数原型为:  



   HHOOK SetWindowsHookEx(int idHook;HOOKPROC lpfn; INSTANCE hMod;DWORD dwThreadId)  



   参数  idHook  表示钩子类型,它是和钩子函数类型一一对应的。比如  WH_KEYBOARD 

表示安装的是键盘钩子,WH_MOUSE  表示是鼠标钩子等。Lpfn  是钩子函数的地址。HMod 

是钩子函数所在的实例的句柄。对于线程钩子,该参数为 NULL ;对于系统钩子,该参数为 

钩子函数所在的 DLL  句柄。dwThreadId  指定钩子所监视的线程的线程号。对于全局钩子, 

该参数为 NULL 。SetWindowsHookEx 返回所安装的钩子句柄。  



   3 .卸载钩子  



    当不再使用钩子时,必须及时卸载。简单地调用函数  BOOL  UnhookWindowsHook 

Ex(HHOOK hhk) 即可。  

   值得注意的是线程钩子和系统钩子的钩子函数的位置有很大的差别 。线程钩子一般在当 

前线程或者当前线程派生的线程内,而系统钩子必须放在独立的动态链接库中,实现起来要 

麻烦一些。  



10。7。3    鼠标钩子应用实例  



实例 10…3:鼠标钩子应用实例。源代码在光盘中“10实例 10…3MouseHook”目录下。  



   本节通过一个鼠标钩子实例来介绍全局钩子的应用方法 。该实例的详细源代码请见附带 

光盘,其中 MouseHookDll  目录下的工程是全局鼠标钩子的实现动态链接库。MouseTest 工程 

通过调用 MouseHookDll  的动态链接库接口安装鼠标钩子并利用。在本例中鼠标钩子函数通 

过判断记录当前窗口的句柄来判断鼠标是否离开窗口边界,并将鼠标位置处的窗口名称实时 

地显示出来。  

   在  MouseHookDll 中实现全局钩子,首先是全局共享数据的实现。这里利用#pragma  



 ·274 ·  


…………………………………………………………Page 286……………………………………………………………

                                                                                        第 10 章    动态链接库  



data_seg 建立一个新的数据段并定义共享数据,其具体格式为:  



     pragma data_seg (〃shareddata〃)  



      HWND sharedwnd=NULL;//共享数据      



      #pragma data_seg()  



      所有在 data_seg pragmas 语句之间声明的变量都将在 shareddata 段中。仅定义一个数据段 

还不能达到共享数据的目的,还要告诉编译器该段的属性,有两种方法可以实现该目的(其 

效果是相同的),一种方法是在 DEF 文件中加入如下语句:  



      SETCTIONS  



      shareddata READ WRITE SHARED  



      另一种方法是在项目设置链接选项中加入如下语句:  



     /SECTION:shareddata;rws  



      MouseHookDll 是一个 MFC 扩展动态链接库,其中包含的安装钩子和卸载钩子的全局函 

数如下:  



      BOOL __stdcall StartHook(HWND hwnd);  



       



      BOOL __stdcall StopHook();  



      全局共享数据声明如下:  



      #pragma data_seg(〃mydata〃)      



      HWND glhPrevTarWnd=NULL;               //上次鼠标所指的窗口句柄      



      HWND glhDisplayWnd=NULL;               //显示目标窗口标题编辑框的句柄      



      HHOOK glhHook=NULL;                    //安装的鼠标勾子句柄      



      HINSTANCE glhInstance=NULL;            //DLL 实例句柄      



      #pragma data_seg()  



      在 DEF 文件中加入如下定义:  



      SECTIONS  



     mydata READ WRITE SHARED  



      在主文件 MouseHookDll。cpp 的 DllMain() 函数中加入保存 DLL 实例句柄的语句如下:  



      extern 〃C〃 int APIENTRY      



      DllMain(HINSTANCE hInstance; DWORD dwReason; LPVOID lpReserved)    



      {    



           UNREFERENCED_PARAMETER(lpReserved);    



           if (dwReason == DLL_PROCESS_ATTACH)    



           {    



                 if (!AfxInitExtensionModule(MouseHookDLL; hInstance))    



                      return 0;    



                 new CDynLinkLibrary(MouseHookDLL);    



                 glhInstance=hInstance;        //插入保存 DLL 实例句柄    



           }    



           else if (dwReason == DLL_PROCESS_DETACH)    



           {    



                                                                                                       ·275 ·  


…………………………………………………………Page 287……………………………………………………………

Visual C++ 6。0 程序设计从入门到精通  



                    AfxTermExtensionModule(MouseHookDLL);    



             }    



             return 1; // ok    



       }  



       这个函数最重要的部分是调用 AfxInitExtensionModule() ,它初始化 DLL 并在 MFC 框架 

中正确地工作。它需要传递给 DllMain() 的 DLL 实例句柄和 AFX_EXTENSION_MODULE 结 

构,结构中存在着对 MFC 有用的信息。  

       加载和卸载鼠标全局钩子的函数接口定义如下:  



       BOOL __stdcall StartHook(HWND hWnd)  



       {                   //install hoook  



             hMouseHook=SetWindowsHookEx(WH_MOUSE;MouseHookProc;glhInstance;0);  



                          //mouse hook  



             if(hMouseHook)  



             {  



                    glhDisplayWnd=hWnd;             //设置显示目标窗口标题编辑框的句柄    



                    return TRUE;  



             }  



             return FALSE;  



       }  



        



       BOOL __stdcall StopHook()  



       {                   //unstall hook  



             BOOL mHook=UnhookWindowsHookEx(hMouseHook);  



             if(mHook)  



                    return TRUE;  



             return FALSE;  



       }  



       钩子函数的具体实现代码如下:  



       LRESULT WINAPI MouseProc(int nCode;WPARAM wparam;LPARAM lparam)      



       {  



             LPMOUSEHOOKSTRUCT pMouseHook=(MOUSEHOOKSTRUCT FAR *) lparam;      



             if (nCode》=0)      



             {      



                    HWND glhTargetWnd=pMouseHook…》hwnd; //取目标窗口句柄      



                    HWND ParentWnd=glhTargetWnd;      



返回目录 上一页 下一页 回到顶部 0 0

你可能喜欢的