消息钩子函数入门篇--(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程序窗口中的编辑框内将显示出鼠标所在的应用程序主窗口的标题

转载于:https://www.cnblogs.com/jh0262/archive/2007/05/15/2946832.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
三:程序的设计: I:设置钩子 设置钩子是通过SetWindowsHookEx ()的API函数. 原形: HHOOK SetWindowsHookEx(int idHook,HOOKPROC lpfn,HINSTANCE hMod,DWORD dwThreadId) idhook:装入钩子的类型. lpfn: 钩子进程的入口地址 hMod: 应用程序的事件句柄 dwThreadId: 装入钩子的线程标示 参数: idHook: 这个参数可以是以下值: WH_CALLWNDPROC、WH_CALLWNDPROCRET、WH_CBT、WH_DEBUG、WH_FOREGROUNDIDLE、WH_GETMESSAGE、WH_JOURNALPLAYBACK、WH_JOURNALRECORD、WH_KEYBOARD、 WH_KEYBOARD_LL、WH_MOUSE、WH_MOUSE_LL、WH_MSGFILTER、WH_SHELL、WH_SYSMSGFILTER。 对于这些参数,我不想一一加以解释,因为MSDN中有关于他们的详细注解。我只挑选其中的几个加以中文说明。 WH_KEYBOARD:一旦有键盘敲打消息(键盘的按下、键盘的弹起),在这个消息被放在应用程序的消息队列前,WINDOWS将会调用你的钩子函数钩子函数可以 改变和丢弃键盘敲打消息。 WH_MOUSE:每个鼠标消息在被放在应用程序的消息队列前,WINDOWS将会调用你的钩子函数钩子函数可以改变和丢弃鼠标消息。 WH_GETMESSAGE:每次当你的应用程序调用一个GetMessage()或者一个PeekMessage()为了去从应用程序的消息队列中要求一个消息时,WINDOWS都会调用你的钩子函数。 而钩子函数可以改变和丢弃这个消息。 II:释放钩子 钩子的释放使用的是UnhookWindowsHookEx()函数 原形:BOOL UnhookWindowsHookEx( HHOOK hhk ) UnhookWindowsHookEx()函数将释放的是钩子链中函数SetWindowsHookEx所装入的钩子进程。 hhk: 将要释放的钩子进程的句柄。 III:钩子进程 钩子进程使用函数HookProc;其实HookProc仅仅只是应用程序定义的符号。比如你可以写成KeyBoardHook.但是参数是不变的。Win32 API提供了诸如:CallWndProc、 GetMsgProc、DebugProc、CBTProc、MouseProc、KeyboardProc、MessageProc等函数,对于他们的详细讲解,可以看MSDN我在此只讲解一下KeyBoardHook的含义。 原形:LRESULT CALLBACK KeyBoardHook (int nCode, WPARAM wParam, LPARAM lParam) 说明:钩子进程是一些依附在一个钩子上的一些函数,因此钩子进程只被WINDOWS调用而不被应用程序调用,他们有时就需要作为一个回调函数(CALLBACK)。 参数说明: nCode:钩子代码,钩子进程使用钩子代码去决定是否执行。而钩子代码的值是依靠钩子的种类来定的。每种钩子种类都有他们自己一系列特性的代码。比如对于WH_KEYBOARD, 钩子代码的参数有:HC_ACTION,HC_NOREMOVE。HC_ACTION的意义:参数wParam 和lParam 包含了键盘敲打消息的信息,HC_NOREMOVE的意义:参数wParam 和lParam包含了 键盘敲打消息的信息,并且,键盘敲打消息一直没有从消息队列中删除。(应用程序调用PeekMessage函数,并且设置PM_NOREMOVE标志)。也就是说当nCode等于HC_ACTION时, 钩子进程必须处理消息。而为HC_NOREMOVE时,钩子进程必须传递消息给CallNextHookEx函数,而不能做进一步的处理,而且必须有CallNextHookEx函数的返回值。 wParam:键盘敲打所产生的键盘消息,键盘按键的虚拟代码。 lParam:包含了消息细节。 注意:如果钩子进程中nCode小于零,钩子进程必须返回(return) CallNextHookEx(nCode,wParam,lParam);而钩子进程中的nCode大于零,但是钩子进程并不处理消息, 作者推荐你调用CallNextHookEx并且返回该函数的返回值。否则,如果另一个应用程序也装入WH_KEYBOARD 钩子,那么该钩子将不接受钩子通知并且返回一个不正确的值。 如果钩子进程处理了消息,它可能返回一个非零值去阻止系统传递该信息到其它剩下的钩子或者windows进程。所以最好在钩子进程的最后都返回CallNextHookEx的返回
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值