消息钩子函数入门篇--(2)示例

由于全局钩子函数必须包含在动态链接库中,所以本例由两个程序体来实现。
1.建立钩子Mousehook.DLL
   (1)选择MFC AppWizard(DLL)创建项目Mousehook;

 (2)选择MFC Extension DLL(共享MFC拷贝)类型;
   (3)由于VC5没有现成的钩子类,所以要在项目目录中创建Mousehook.h文件,在其中建立钩子类:
   class AFX_EXT_CLASS Cmousehook:public CObject
   {
   public:
   Cmousehook();
   //钩子类的构造函数
   ~Cmousehook();
   //钩子类的析构函数
   BOOL starthook(HWND hWnd);
   //安装钩子函数
   BOOL stophook();
   卸载钩子函数
   };
   (4)在Mousehook.app文件的顶部加入#include"Mousehook.h"语句;
   (5)加入全局共享数据变量:
   #pragma data_seg("mydata")
   HWND glhPrevTarWnd=NULL;
   //上次鼠标所指的窗口句柄
   HWND glhDisplayWnd=NULL;
   //显示目标窗口标题编辑框的句柄
   HHOOK glhHook=NULL;
   //安装的鼠标钩子句柄
   HINSTANCE glhInstance=NULL;
   //DLL实例句柄
   #pragma data_seg()
   (6)在DEF文件中定义段属性:
   SECTIONS
   mydata READ WRITE SHARED
   (7)在主文件Mousehook.cpp的DllMain函数中加入保存DLL实例句柄的语句:
   DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
   {
   //如果使用lpReserved参数则删除下面这行
   UNREFERENCED_PARAMETER(lpReserved);
   if (dwReason == DLL_PROCESS_ATTACH)
   {
   TRACE0("MOUSEHOOK.DLL Initializing!/n");
   //扩展DLL仅初始化一次
   if (!AfxInitExtensionModule(MousehookDLL, hInstance))
   return 0;
   new CDynLinkLibrary(MousehookDLL);
   //把DLL加入动态MFC类库中
   glhInstance=hInstance;
   //插入保存DLL实例句柄
   }
   else if (dwReason == DLL_PROCESS_DETACH)
   {
   TRACE0("MOUSEHOOK.DLL Terminating!/n");
   //终止这个链接库前调用它
   AfxTermExtensionModule(MousehookDLL);
   }
   return 1;
   }
   (8)类Cmousehook的成员函数的具体实现:
   Cmousehook::Cmousehook()
   //类构造函数
   {
   }
   Cmousehook::~Cmousehook()
   //类析构函数
   {
   stophook();
   }
   BOOL Cmousehook::starthook(HWND hWnd)
   //安装钩子并设定接收显示窗口句柄
   {
   BOOL bResult=FALSE;
   glhHook=SetWindowsHookEx(WH_MOUSE,MouseProc,glhInstance,0);
   if(glhHook!=NULL)
   bResult=TRUE;
   glhDisplayWnd=hWnd;
   //设置显示目标窗口标题编辑框的句柄
   return bResult;
   }
   BOOL Cmousehook::stophook()
   //卸载钩子
   {
   BOOL bResult=FALSE;
   if(glhHook)
   {
   bResult= UnhookWindowsHookEx(glhHook);
   if(bResult)
   {
   glhPrevTarWnd=NULL;
   glhDisplayWnd=NULL;//清变量
   glhHook=NULL;
   }
   }
   return bResult;
   }
   (9)钩子函数的实现:
   LRESULT WINAPI MouseProc(int nCode,WPARAM wparam,LPARAM lparam)
   {
   LPMOUSEHOOKSTRUCT pMouseHook=(MOUSEHOOKSTRUCT FAR *) lparam;
   if (nCode>=0)
   {
   HWND glhTargetWnd=pMouseHook->hwnd;
   //取目标窗口句柄
   HWND ParentWnd=glhTargetWnd;
   while (ParentWnd !=NULL)
   {
   glhTargetWnd=ParentWnd;
   ParentWnd=GetParent(glhTargetWnd);
   //取应用程序主窗口句柄
   }
   if(glhTargetWnd!=glhPrevTarWnd)
   {
   char szCaption[100];
   GetWindowText(glhTargetWnd,szCaption,100);
   //取目标窗口标题
   if(IsWindow(glhDisplayWnd))
   SendMessage(glhDisplayWnd,WM_SETTEXT,0,(LPARAM)(LPCTSTR)szCaption);
   glhPrevTarWnd=glhTargetWnd;
   //保存目标窗口
   }
   }
   return CallNextHookEx(glhHook,nCode,wparam,lparam);
   //继续传递消息
   }
   (10)编译项目生成mousehook.dll。
   2.创建钩子可执行程序
   (1)用MFC的AppWizard(EXE)创建项目Mouse;
   (2)选择“基于对话应用”并按下“完成”键;
   (3)编辑对话框,删除其中原有的两个按钮,加入静态文本框和编辑框,用鼠标右键点击静态文本框,在弹出的菜单中选择“属性”,设置其标题为“鼠标所在的窗口标题”;

   (4)在Mouse.h中加入对Mousehook.h的包含语句#Include"../Mousehook/Mousehook.h";
   (5)在CMouseDlg.h的CMouseDlg类定义中添加私有数据成员:
   CMouseHook m_hook;//加入钩子类作为数据成员
   (6)修改CmouseDlg::OnInitDialog()函数:
   BOOL CMouseDlg::OnInitDialog()
   {
   CDialog::OnInitDialog();
   ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); 

         ASSERT(IDM_ABOUTBOX <0xF000);
   CMenu* pSysMenu = GetSystemMenu(FALSE);
   if (pSysMenu != NULL)
   {
   CString strAboutMenu;
   strAboutMenu.LoadString(IDS_ABOUTBOX);
   if (!strAboutMenu.IsEmpty())
   {
   pSysMenu->AppendMenu(MF_SEPARATOR);
   pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
   }
   }
   SetIcon(m_hIcon, TRUE);//Set big icon
   SetIcon(m_hIcon, FALSE);//Set small icon
   //TODO: Add extra initialization here
   CWnd * pwnd=GetDlgItem(IDC_EDIT1);
   //取得编辑框的类指针
   m_hook.starthook(pwnd->GetSafeHwnd());
   //取得编辑框的窗口句柄并安装钩子
   return TRUE;
   //return TRUE unless you set the focus to a control
   }
   (7)链接DLL库,即把../Mousehook/debug/Mousehook.lib加入到项目设置链接标签中;
   (8)编译项目生成可执行文件;
   (9)把Mousehook.DLL拷贝到../mouse/debug目录中;
   (10)先运行几个可执行程序,然后运行Mouse.exe程序,把鼠标在不同窗口中移动,在Mouse.exe程序窗口中的编辑框内将显示出鼠标所在的应用程序主窗口的标题

posted @ 2007-05-15 15:54  巨巨  阅读(296)  评论(0编辑  收藏  举报