【小沐学C++】C++ 实现鼠标键盘钩子HOOK
文章目录
- 1、简介
- 2、相关函数
- 2.1 SetWindowsHookEx
- 2.2 UnhookWindowsHookEx
- 2.3 CallNextHookEx
- 3、相关结构体
- 3.1 KBDLLHOOKSTRUCT
- 3.2 MSLLHOOKSTRUCT
- 4、挂钩过程
- 5、代码测试
- 5.1 代码1
- 结语
1、简介
https://learn.microsoft.com/zh-cn/windows/win32/winmsg/about-hooks
挂钩是应用程序截获消息、鼠标操作和击键等事件的机制。 截获特定类型的事件的函数称为 挂钩过程。 挂钩过程可以对其接收的每个事件执行操作,然后修改或放弃该事件。

挂钩是系统消息处理机制中的一个点,其中应用程序可以安装子例程来监视系统中的消息流量,并在某些类型的消息到达目标窗口过程之前对其进行处理。

以下一些示例使用 挂钩:
- 监视用于调试的消息
- 支持录制和播放宏
- 为帮助密钥 (F1) 提供支持
- 模拟鼠标和键盘输入
- 实现基于计算机的训练 (CBT) 应用程序

2、相关函数
2.1 SetWindowsHookEx
将应用程序定义的挂钩过程安装到挂钩链中。 你将安装挂钩过程来监视系统的某些类型的事件。 这些事件与特定线程或与调用线程位于同一桌面中的所有线程相关联。
HHOOK SetWindowsHookExA([in] int idHook,[in] HOOKPROC lpfn,[in] HINSTANCE hmod,[in] DWORD dwThreadId
);HHOOK SetWindowsHookExW([in] int idHook,[in] HOOKPROC lpfn,[in] HINSTANCE hmod,[in] DWORD dwThreadId
);
- WH_KEYBOARD
安装用于监视击键消息的挂钩过程。 有关详细信息,请参阅 KeyboardProc 挂钩过程。
LRESULT CALLBACK KeyboardProc(_In_ int code,_In_ WPARAM wParam,_In_ LPARAM lParam
);
- WH_KEYBOARD_LL
安装用于监视低级别键盘输入事件的挂钩过程。 有关详细信息,请参阅 [LowLevelKeyboardProc] (/windows/win32/winmsg/lowlevelkeyboardproc) 挂钩过程。
LRESULT CALLBACK LowLevelKeyboardProc(_In_ int nCode,_In_ WPARAM wParam,_In_ LPARAM lParam
);
// 其中lParam指向 KBDLLHOOKSTRUCT 结构的指针。
- WH_MOUSE
安装监视鼠标消息的挂钩过程。 有关详细信息,请参阅 MouseProc 挂钩过程。
LRESULT CALLBACK MouseProc(_In_ int nCode,_In_ WPARAM wParam,_In_ LPARAM lParam
);
- WH_MOUSE_LL
安装用于监视低级别鼠标输入事件的挂钩过程。 有关详细信息,请参阅 LowLevelMouseProc 挂钩过程。
LRESULT CALLBACK LowLevelMouseProc(_In_ int nCode,_In_ WPARAM wParam,_In_ LPARAM lParam
);
// 其中lParam指向 MSLLHOOKSTRUCT 结构的指针。
2.2 UnhookWindowsHookEx
删除 SetWindowsHookEx 函数安装在挂钩链中的挂钩过程。
BOOL UnhookWindowsHookEx([in] HHOOK hhk
);
2.3 CallNextHookEx
将挂钩信息传递给当前挂钩链中的下一个挂钩过程。 挂钩过程可以在处理挂钩信息之前或之后调用此函数。
LRESULT CallNextHookEx([in, optional] HHOOK hhk,[in] int nCode,[in] WPARAM wParam,[in] LPARAM lParam
);
3、相关结构体
3.1 KBDLLHOOKSTRUCT
包含有关低级别键盘输入事件的信息。
typedef struct tagKBDLLHOOKSTRUCT {DWORD vkCode;DWORD scanCode;DWORD flags;DWORD time;ULONG_PTR dwExtraInfo;
} KBDLLHOOKSTRUCT, *LPKBDLLHOOKSTRUCT, *PKBDLLHOOKSTRUCT;
3.2 MSLLHOOKSTRUCT
包含有关低级别鼠标输入事件的信息。
typedef struct tagMSLLHOOKSTRUCT {POINT pt;DWORD mouseData;DWORD flags;DWORD time;ULONG_PTR dwExtraInfo;
} MSLLHOOKSTRUCT, *LPMSLLHOOKSTRUCT, *PMSLLHOOKSTRUCT;
4、挂钩过程
- 定义挂钩过程
为了利用特定类型的挂钩,开发人员提供了一个挂钩过程,并使用 SetWindowsHookEx 函数将其安装到与挂钩关联的链中。 挂钩过程必须具有以下语法:
LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam
)
{// process event...return CallNextHookEx(NULL, nCode, wParam, lParam);
}
SetWindowsHookEx 函数始终在挂钩链的开头安装挂钩过程。 当发生由特定类型的挂钩监视的事件时,系统会在与挂钩关联的挂钩链的开头调用过程。 链中的每个挂钩过程确定是否将事件传递给下一个过程。 挂钩过程通过调用 CallNextHookEx 函数将事件传递给下一过程。
- 安装和释放挂钩过程
SetWindowsHookEx 传递模块句柄、指向挂钩过程入口点的指针,以及线程标识符的 0,指示挂钩过程应与调用线程位于同一桌面中的所有线程相关联。 以下示例中显示了此序列。
HOOKPROC hkprcSysMsg;
static HINSTANCE hinstDLL;
static HHOOK hhookSysMsg; hinstDLL = LoadLibrary(TEXT("c:\\myapp\\sysmsg.dll"));
hkprcSysMsg = (HOOKPROC)GetProcAddress(hinstDLL, "SysMessageProc"); hhookSysMsg = SetWindowsHookEx( WH_SYSMSGFILTER,hkprcSysMsg,hinstDLL,0);
可以通过调用 UnhookWindowsHookEx 函数来释放特定于线程的挂钩过程, (从挂钩链) 中删除其地址,并指定要释放的挂钩过程的句柄。 一旦应用程序不再需要挂钩过程,就立即释放它。
5、代码测试
5.1 代码1
#include "pch.h"
#include <Windows.h>
#include <iostream>std::string get_time()
{SYSTEMTIME sys;GetLocalTime(&sys);char time[255] = { 0 };sprintf_s(time, "[%4d/%02d/%02d %02d:%02d:%02d]", sys.wYear, sys.wMonth, sys.wDay, sys.wHour, sys.wMinute, sys.wSecond);return std::string(time);
}LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{/*typedef struct tagKBDLLHOOKSTRUCT {DWORD vkCode; // 按键代号DWORD scanCode; // 硬件扫描代号,同 vkCode 也可以作为按键的代号。DWORD flags; // 事件类型,一般按键按下为 0 抬起为 128。DWORD time; // 消息时间戳ULONG_PTR dwExtraInfo; // 消息附加信息,一般为 0。}KBDLLHOOKSTRUCT,*LPKBDLLHOOKSTRUCT,*PKBDLLHOOKSTRUCT;*/KBDLLHOOKSTRUCT* ks = (KBDLLHOOKSTRUCT*)lParam; // 包含低级键盘输入事件信息char buffer[255];DWORD code = ks->vkCode;std::string t = get_time();char state[20];if (wParam == WM_KEYDOWN){strcpy_s(state, "按下");}else if (wParam == WM_KEYUP){strcpy_s(state, "抬起");}sprintf_s(buffer, "[键盘]%s 键代码:%d %s", t.c_str(), code, state);std::cout << buffer << std::endl;//return 1; // 拦截消息return CallNextHookEx(NULL, nCode, wParam, lParam);
}LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{/*typedef struct tagMOUSEHOOKSTRUCT {POINT pt; // Point数据HWND hwnd; // 接收鼠标消息的窗体的句柄UINT wHitTestCode; // 指定点击测试值ULONG_PTR dwExtraInfo; // 指定和该消息相关联的附加信息。} MOUSEHOOKSTRUCT, FAR* LPMOUSEHOOKSTRUCT, * PMOUSEHOOKSTRUCT;*/MOUSEHOOKSTRUCT* ms = (MOUSEHOOKSTRUCT*)lParam;POINT pt = ms->pt;std::string time = get_time();char buffer[1024];char state[20] = "未知";if (wParam == WM_LBUTTONDOWN){strcpy_s(state, "左键按下");}else if (wParam == WM_LBUTTONUP){strcpy_s(state, "左键抬起");}else if (wParam == WM_RBUTTONDOWN){strcpy_s(state, "右键按下");}else if (wParam == WM_RBUTTONUP){strcpy_s(state, "右键抬起");}else if (wParam == WM_MOUSEMOVE){strcpy_s(state, "移动");}sprintf_s(buffer, "[鼠标]%s 键代码:x:%d y:%d %s", time.c_str(), pt.x, pt.y, state);std::cout << buffer << std::endl;//return 1; // 拦截消息return CallNextHookEx(NULL, nCode, wParam, lParam);}int main()
{HINSTANCE hM = GetModuleHandle(NULL), hK = GetModuleHandle(NULL);HHOOK g_Hook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardProc, hK, 0);HHOOK g_Hook2 = SetWindowsHookEx(WH_MOUSE_LL, MouseProc, hM, 0);// 消息循环MSG msg;while (GetMessage(&msg, NULL, 0, 0)){TranslateMessage(&msg);DispatchMessage(&msg);}UnhookWindowsHookEx(g_Hook);return 0;
}

结语
如果您觉得该方法或代码有一点点用处,可以给作者点个赞,或打赏杯咖啡;╮( ̄▽ ̄)╭
如果您感觉方法或代码不咋地//(ㄒoㄒ)//,就在评论处留言,作者继续改进;o_O???
如果您需要相关功能的代码定制化开发,可以留言私信作者;(✿◡‿◡)
感谢各位大佬童鞋们的支持!( ´ ▽´ )ノ ( ´ ▽´)っ!!!
相关文章:
【小沐学C++】C++ 实现鼠标键盘钩子HOOK
文章目录 1、简介2、相关函数2.1 SetWindowsHookEx2.2 UnhookWindowsHookEx2.3 CallNextHookEx 3、相关结构体3.1 KBDLLHOOKSTRUCT3.2 MSLLHOOKSTRUCT 4、挂钩过程5、代码测试5.1 代码1 结语 1、简介 https://learn.microsoft.com/zh-cn/windows/win32/winmsg/about-hooks 挂…...
【pycharm】常见问题与解决
记录一些Pycharm中经常遇到的问题 1. “Open file or Project” always in loading state (hang) a) 老版本 (2021年左右) since build 211.6693.14, it is possible to use a native file chooser on Windows. The feature is experimental; to enable it, add the followi…...
flask web学习之表单(一)
文章目录 一、使用Flask-WTF处理表单1.1 安装Flask-WTF库1.2 定义WTForms表单类常用的WTForm字段实例化字段类常用参数常用的WTForm验证器 1.3 输出HTML代码使用render_kw属性在调用字段时传入 1.4 在模板中渲染表单 在web程序中,表单是用户交互最常见的方式之一。用…...
@ControllerAdvice 使用场景
ControllerAdvice 是Spring 框架中的注解,多用在Spring MVC应用程序中。 使用场景1:处理异常 # 示例1 import org.apache.ibatis.javassist.NotFoundException; import org.springframework.http.HttpStatus; import org.springframework.http.Respons…...
二极管选型怎么选?常用参数要熟练~
同学们大家好,今天我们继续学习杨欣的《电子设计从零开始》,这本书从基本原理出发,知识点遍及无线电通讯、仪器设计、三极管电路、集成电路、传感器、数字电路基础、单片机及应用实例,可以说是全面系统地介绍了电子设计所需的知识…...
【小白专用】C#关于角色权限系统
(C#)用户、角色、权限 https://www.cnblogs.com/huangwen/articles/638050.html 权限管理系统——数据库的设计(一) https://www.cnblogs.com/cmsdn/p/3371576.html 权限管理系统——菜单模块的实现(二) …...
代码随想录算法训练营
一刷打卡记录: 日期打卡2023/10/25 day01二分查找有点转不过弯,快慢指针能理解,自己写也可能写不出来,但是能记住了,能看懂,还有其他解法待补充看完,花了挺长时间的2023/10/26 day02还好&#…...
统计学-R语言-3
文章目录 前言给直方图增加正态曲线的不恰当之处直方图与条形图的区别核密度图时间序列图洛伦茨曲线计算绘制洛伦茨曲线所需的各百分比数值绘制洛伦茨曲线 练习 前言 本篇文章是介绍对数据的部分图形可视化的图型展现。 给直方图增加正态曲线的不恰当之处 需要注意的是&#…...
spring动态控制定时任务
在spring框架中,对于简单的定时任务,可以使用 Scheduled 注解实现,在实际项目中,经常需要动态的控制定时任务,比如通过接口增加、启动、停止、删除定时任务,动态的改变定时任务的执行时间等。 我们可以通过…...
3. Mybatis 中SQL 执行原理
2. Mybatis 中SQL 执行原理 这里有两种方式,一种为常用的 Spring 依赖注入 Mapper 的方式。另一种为直接使用 SqlSessionTemplate 执行 Sql 的方式。 Spring 依赖注入 Mapper 的方式 Mapper 接口注入 SpringIOC 容器 Spring 容器在扫描 BeanDefinition 阶段会扫…...
第一次在RUST官方论坛上留言发布我的Rust板箱
第一次在RUST官方论坛上发帖子,有点紧张~地址在这里: 【My Rust Crate】obtains linux local information - The Rust Programming Language Forum (rust-lang.org)...
LabVIEW 智能化矿用定向钻机液压系统监测
简介 在矿用定向钻机的液压系统监测中,实现实时监控和异常预警对于保障设备运行的稳定性至关重要。传统的人工监测方法效率低下而且准确性不能满足要求,针对这种情况采用 LabVIEW 开发平台,设计并实现了一套智能化矿用定向钻机液压系统的状态…...
GO数据库操作
Golang 出色的 ORM 库为 GORM。 官网文档:https://gorm.io/docs/ 我们来说说增删改查的用法,更深入的研究可以去官网看看。 GORM功能概览: 关联(有一个、有多个、属于、多对多、多态性、单表继承)挂钩(创…...
PyTorch简单理解ChannelShuffle与数据并行技术解析
目录 torch.nn子模块详解 nn.ChannelShuffle 用法与用途 使用技巧 注意事项 参数 示例代码 nn.DataParallel 用法与用途 使用技巧 注意事项 参数 示例 nn.parallel.DistributedDataParallel 用法与用途 使用技巧 注意事项 参数 示例 总结 torch.nn子模块详…...
MySQL 8查询语句之查询所有字段、特定字段、去除重复字段、Where判断条件
《MySQL 8创建数据库、数据表、插入数据并且查询数据》里边有我使用到的数据。 再使用下方的语句补充一些数据: insert into Bookbought.bookuser(id,username,userphone,userage,sex,userpassword) values (11,Book Break,22245678911,18,male,good#111); insert…...
LLaMA-Factory添加adalora
感谢https://github.com/tsingcoo/LLaMA-Efficient-Tuning/commit/f3a532f56b4aa7d4200f24d93fade4b2c9042736和https://github.com/huggingface/peft/issues/432的帮助。 在LLaMA-Factory中添加adalora 1. 修改src/llmtuner/hparams/finetuning_args.py代码 在FinetuningArg…...
多端多用户万能DIY商城系统源码:自营+多商户入驻商城系统 独立部署 带完整的安装代码包以及搭建教程
电子商务行业日新月异,许多企业希望能够通过线上商城拓展业务。但是,传统商城系统往往无法满足多样化、个性化的需求,而且开发周期长、成本高。罗峰就来给大家分享一款多端多用户万能DIY商城系统源码,搭建简单。 以下是部分代码示…...
Qt 6之七:学习资源
Qt 6之七:学习资源 Qt是一种跨平台的C应用程序开发框架,它提供了一套丰富的工具和库,可以帮助开发者快速构建跨平台的应用程序,用于开发图形用户界面(GUI)和非GUI应用程序。 Qt 6之一:简介、安…...
解决大模型的幻觉问题:一种全新的视角
在人工智能领域,大模型已经成为了一个重要的研究方向。然而,随着模型规模的不断扩大,一种新的问题开始浮出水面,那就是“幻觉”问题。这种问题的出现,不仅影响了模型的性能,也对人工智能的发展带来了新的挑…...
mysql进阶-重构表
目录 1. 原因 2. 如何重构表呢? 2.1 命令1: 2.2 命令2: 2.3 命令3: 1. 原因 正常的业务开发,为什么需要重构表呢? 原因1:某张表存在大量的新增和删除操作,导致表经历过大量的…...
基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...
基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...
python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
2024年赣州旅游投资集团社会招聘笔试真
2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...
DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...
第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...
WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...
3403. 从盒子中找出字典序最大的字符串 I
3403. 从盒子中找出字典序最大的字符串 I 题目链接:3403. 从盒子中找出字典序最大的字符串 I 代码如下: class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...
爬虫基础学习day2
# 爬虫设计领域 工商:企查查、天眼查短视频:抖音、快手、西瓜 ---> 飞瓜电商:京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空:抓取所有航空公司价格 ---> 去哪儿自媒体:采集自媒体数据进…...
