随笔 - 54  文章 - 0  评论 - 4  阅读 - 49797

HOOK - 低级鼠标Hook

参考博客

一、SetWindowsHookEx
HHOOK WINAPI SetWindowsHookEx(
__in int idHook, \\钩子类型
__in HOOKPROC lpfn, \\回调函数地址
__in HINSTANCE hMod, \\实例句柄
__in DWORD dwThreadId); \\线程ID

这里使用的钩子类型idHook 是WH_MOUSE_LL。

在使用SetWindowsHook截获鼠标事件时,如果使用WH_MOUSE参数,则只能监控钩子所在模块的鼠标事件。

如需要截获整个系统的鼠标事件,那么使用WH_MOUSE_LL参数。

 

二、自定义消息通信

这里和参考的一样,将其写成MFC DLL然后使用导出函数。

通过发送消息SendMessage的方式,让dll和主程序进行通信(SendMessage 同步),

这里要注意使用的是自定义消息的方式来进行通信,就像IPC中的自定义消息一样,.dll与MFC中的消息定义必须完全一样:

1 //自定义消息,用于处理dll发来的消息
2 //该消息的定义和dll中定义的消息必须一样
3 #define WM_MOUSEMESSAGE WM_USER + 100

 

 

DLL部分代码:

.dll中

复制代码
 1 // 安装低级鼠标子函数,截获系统所有的鼠标消息
 2 BOOL WINAPI StartHookMouse(HWND hwnd)
 3 {
 4     //这里自身的窗口句柄传过来
 5 
 6     __hWnd = hwnd;
 7 
 8 
 9 
10 
11     /*
12     在使用SetWindowsHook截获鼠标事件时,如果使用WH_MOUSE参数,则只能监控钩子所在模块的鼠标事件。
13 如需要截获整个系统的鼠标事件,那么使用WH_MOUSE_LL参数。
14     
15     */
16     __hhkMouse = SetWindowsHookEx(
17         WH_MOUSE_LL,
18         LowLevelMouseProc,
19         __hInstance,
20         0
21     );
22 
23     if (NULL == __hhkMouse)
24     {
25         return FALSE;
26     }
27     else
28     {
29         return TRUE;
30     }
31 
32 }
复制代码

 

复制代码
 1 // 定义低级鼠标子函数
 2 LRESULT CALLBACK LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam)
 3 {
 4     // 有鼠标消息时,将其发给主程序
 5 
 6     if (__hWnd != NULL && nCode == HC_ACTION)//HC_ACTION 有鼠标信息
 7     {
 8         //通知MFC
 9         ::SendMessage(__hWnd, WM_MOUSEMESSAGE, wParam, lParam);
10     }
11 
12     return CallNextHookEx(__hhkMouse, nCode, wParam, lParam);
13 
14 }
复制代码

然后,主程序收到该消息后,将其显示在程序界面上。

这边为了给主程序发送消息,在主程序调用安装鼠标钩子的函数时,我们需要将主窗口的句柄通过参数传递到dll中,这样我们就可以发送消息给主程序了。

 

三、共享代码段,所有线程共享

如果一个程序运行了两个实例,很遗憾,这两个程序的代码并不会共享,因为程序代码在程序运行时就被装载到内存,第二个程序再启动时,系统没法判断也不会判断这个程序是否还是原来的程序(如果程序被更新或更改),所以仍然会把程序代码重新加载到内存的另一块区域。

代码的共享体现应该是链接库中,特别是动态链接库中。因为库被设计成动态链接的,所以程序可以在运行后再确定代码所在的内存地址,这也就能实现多个程序调用同一块代码了。

 

1 // 共享代码段,所有线程共享
2 #pragma data_seg("SHARED")
3 static HHOOK __hhkMouse = NULL;            // 鼠标钩子句柄
4 static HINSTANCE __hInstance = NULL;    // 本DLL的实例句柄
5 static HWND __hWnd = NULL;                // 调用DLL的主窗口句柄
6 #pragma data_seg()
7 #pragma comment(linker,"/section:SHARED,rws")

四、卸载hook

// 卸载低级鼠标钩子
VOID WINAPI StopHookMouse()
{
if (__hhkMouse != NULL)
{
::UnhookWindowsHookEx(__hhkMouse);
}
}

 

/***********************************/

五、MFC中的自定义消息

首先必须得和dll中的完全一样,定义一个自定义消息,必须完全一样

(这里可以参考博客http://www.cnblogs.com/hcxblog/archive/2012/10/02/2710261.html)

然后要写自定义消息的三句话:

1.消息映射

2.消息处理函数的声明

3.消息处理函数的实现

    ON_MESSAGE(WM_MOUSEMESSAGE, &CLowLevelHookMouseDlg::OnMouseMessage) //消息映射

    afx_msg LRESULT OnMouseMessage(WPARAM wParam, LPARAM lParam);



LRESULT CLowLevelHookMouseDlg::OnMouseMessage(
    WPARAM wParam, LPARAM lParam)

 

----------------------------------------------------------------------------------------

使用函数:

1 HINSTANCE __hInstanceDll = NULL;
2 
3 typedef BOOL (CALLBACK *StartHookMouse)(HWND hwnd);
4 typedef VOID (CALLBACK *StopHookMouse)();
复制代码
 1 //启动鼠标钩子
 2 void CLowLevelHookMouseDlg::OnBnClickedButtonStarthook()
 3 {
 4     // TODO: 在此添加控件通知处理程序代码
 5     __hInstanceDll = LoadLibrary(_T("HookDll.dll"));
 6     if (__hInstanceDll == NULL)
 7     {
 8         ::MessageBox(NULL,(LPCTSTR)GetLastError(),L"LoadLibrary() Error",0);
 9         return;
10     }
11 
12     StartHookMouse StartHook;
13     StartHook = (StartHookMouse)::GetProcAddress(
14         __hInstanceDll, "StartHookMouse");
15     if (StartHook == NULL)
16     {
17         ::MessageBox(NULL, (LPCTSTR)GetLastError(), L"GetProcAddress() Error", 0);
18     }
19 
20     if (StartHook(this->m_hWnd))
21     {
22         m_List.InsertItem(m_List.GetItemCount(), _T("0"));
23         m_List.SetItemText(m_List.GetItemCount() - 1, 1, _T("0"));
24         m_List.SetItemText(m_List.GetItemCount() - 1, 2, _T("启动鼠标钩子成功"));
25 
26         CButton *pButton = (CButton *)GetDlgItem(IDC_BUTTON_STARTHOOK)->EnableWindow(FALSE);
27 
28         CButton *Button = (CButton *)GetDlgItem(IDC_BUTTON_STOPHOOK)->EnableWindow(TRUE);
29 
30     }
31     else
32     {
33         m_List.InsertItem(m_List.GetItemCount(), _T("0"));
34         m_List.SetItemText(m_List.GetItemCount() - 1, 1, _T("0"));
35         m_List.SetItemText(m_List.GetItemCount() - 1, 2, _T("启动鼠标钩子失败"));
36     }
37 }
38 
39 //结束鼠标钩子
40 void CLowLevelHookMouseDlg::OnBnClickedButtonStophook()
41 {
42     // TODO: 在此添加控件通知处理程序代码
43 
44     StopHookMouse StopHook;
45     __hInstanceDll = LoadLibrary(_T("HookDll.dll"));
46     if (__hInstanceDll == NULL)
47     {
48         ::MessageBox(NULL, (LPCTSTR)GetLastError(), L"LoadLibrary() Error", 0);
49         return;
50     }
51 
52     StopHook = (StopHookMouse) ::GetProcAddress(
53         __hInstanceDll, "StopHookMouse");
54 
55     if (StopHook == NULL)
56     {
57         m_List.InsertItem(m_List.GetItemCount(), _T("0"));
58         m_List.SetItemText(m_List.GetItemCount() - 1, 1, _T("0"));
59         m_List.SetItemText(m_List.GetItemCount() - 1, 2, _T("获取函数 StopHookMouse 失败"));
60         
61         return;
62     }
63     else
64     {
65         StopHook();
66         m_List.InsertItem(m_List.GetItemCount(), _T("0"));
67         m_List.SetItemText(m_List.GetItemCount() - 1, 1, _T("0"));
68         m_List.SetItemText(m_List.GetItemCount() - 1, 2, _T("停止HOOKMOUSE成功"));
69         CButton *pButton = (CButton *)GetDlgItem(IDC_BUTTON_STOPHOOK)->EnableWindow(FALSE);
70         
71         CButton *Button = (CButton *)GetDlgItem(IDC_BUTTON_STARTHOOK)->EnableWindow(TRUE);
72 
73     }
74 
75     if (__hInstanceDll != NULL)
76     {
77         ::FreeLibrary(__hInstanceDll);
78     }
79 
80     // 确保list control 最后一行可见 跳转到stop那行
81     m_List.EnsureVisible(m_List.GetItemCount() - 1, FALSE);
82 
83 }
复制代码

 

 

 

六、最后

剩下的都是一些简单的实现了,这里觉得重要的写在了上面。其他的实现比较常规。

1.其中有两个checkbox的实现做了发现没有达到想要的效果就废掉了。

2.还有就是源博主中如果多点了几次hook,在unhook的时候会出问题,所以这里

        CButton *pButton = (CButton *)GetDlgItem(IDC_BUTTON_STOPHOOK)->EnableWindow(FALSE);

Ring3 x86 x64 通过.

以上就是本次的一个小总结,如有不妥还请批评指正。

再次感谢。

 

代码:
链接:http://pan.baidu.com/s/1dEPx03J  密码:y463

 

IPC自定义消息代码:

链接:http://pan.baidu.com/s/1o795ZRW 密码:dt6p

 

posted on   czhang4  阅读(643)  评论(0编辑  收藏  举报
编辑推荐:
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
阅读排行:
· C# 13 中的新增功能实操
· Ollama本地部署大模型总结
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(4)
· langchain0.3教程:从0到1打造一个智能聊天机器人
· 2025成都.NET开发者Connect圆满结束
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示