一、后台钩子截图调用示例
二、钩子的个人理解
- 挂接钩子的步骤:SetWindowsHookEx -> UnhookWindowsHookEx,直接用SetWindowsHookEx 函数挂接到对应的钩子类型和处理函数中;当钩子使用完后需要调用UnhookWindowsHookEx函数卸载(因为钩子消耗系统性能)。
SetWindowsHookEx 函数原型如下:
//! int idHook 所监控的挂钩类型 //! HOOKPROC lpfn 监控信息的处理函数 //! HINSTANCEhMod 监控信息的动态链接位置 nullptr则与本线程相关 //! DWORD dwThreadId 挂钩线程id 0则代表当前 决定了此钩子是系统钩子还是线程钩子 //! 返回值 函数执行成功,则返回值为对应的钩子句柄;若此函数执行失败,则返回值为NULL(0) HHOOK SetWindowsHookEx(int idHook, HOOKPROC lpfn, HINSTANCE hMod, DWORD dwThreadId);
讯享网
SetWindowsHookEx 函数原型如下:
讯享网 //! hHook 要卸载的钩子句柄 BOOL UnhookWindowsHookEx(HHOOK hHook);
- 各个类型的钩子原型一致,如下:
/ * @brief Hookproc * @param code 这是一个整数值,用于指定发送到钩子过程的消息类型。它可以是几个值中的一个,例如HC_ACTION、HC_NOREMOVE或HC_CREATE * @param wParam 一个指向宽字符值的指针,其中包含有关发送到钩子过程的消息的附加信息,其值取决于code的值 * @param lParam 一个指向长字符值的指针,其中包含有关发送到钩子过程的消息的附加信息,其值取决于code的值 * @return 如果返回0,则消息未被处理,将继续由其他钩子或目标窗口处理。如果返回非零值,则消息已被钩子过程处理,不会被其他钩子或目标窗口处理 */ LRESULT Hookproc(int code, WPARAM wParam, LPARAM lParam)
- 不同的钩子对应的数据结构体及参数含义不同,如当关联键盘钩子(WH_KEYBOARD_LL)时,其lParam参数代表的结构体为KBDLLHOOKSTRUCT;当关联鼠标钩子(WH_MOUSE_LL)时,其wParam代表鼠标操作的类型(如左键按下、放开等),lParam参数代表的结构体为MSLLHOOKSTRUCT。具体可按需求查看对应内容。
- 推荐的链接:官方链接、钩子(HOOK)函数教程
三、源码
CHook.h
讯享网#ifndef CHOOK_H #define CHOOK_H // 干净的钩子类 class CHook {
public: explicit CHook(); ~CHook(); }; #endif // CHOOK_H
CHook.cpp
#include "CHook.h" #include "CMainWindow.h" #include <windows.h> #include <QDebug> // 引用全局变量 extern CMainWindow *g_mainWdindow; HHOOK g_hook; // 钩子对象 / * @brief Hookproc * @param code 这是一个整数值,用于指定发送到钩子过程的消息类型。它可以是几个值中的一个,例如HC_ACTION、HC_NOREMOVE或HC_CREATE * @param wParam 一个指向宽字符值的指针,其中包含有关发送到钩子过程的消息的附加信息,其值取决于code的值 * @param lParam 一个指向长字符值的指针,其中包含有关发送到钩子过程的消息的附加信息,其值取决于code的值 * @return 如果返回0,则消息未被处理,将继续由其他钩子或目标窗口处理。如果返回非零值,则消息已被钩子过程处理,不会被其他钩子或目标窗口处理 */ LRESULT Hookproc(int code, WPARAM wParam, LPARAM lParam) {
// lParam强转为键盘数据结构体 KBDLLHOOKSTRUCT *data = (KBDLLHOOKSTRUCT *)lParam; //! GetAsyncKeyState //! 获取指定按钮状态:非0则为按下状态,为0则为未按下状态 // 当Ctrl、Alt、X都按下时进入 if(GetAsyncKeyState(VK_LCONTROL) && GetAsyncKeyState(VK_LMENU) && 0x58 == data->vkCode && g_mainWdindow->screenShotFlag()) {
// 调用截图 g_mainWdindow->startScreenShot(); } return CallNextHookEx(g_hook, code, wParam, lParam); } CHook::CHook() {
//! SetWindowsHookEx 函数解释 //! int idHook 所监控的挂钩类型 //! HOOKPROC lpfn 监控信息的处理函数 //! HINSTANCEhMod 监控信息的动态链接位置 nullptr则与本线程相关 //! DWORD dwThreadId 挂钩线程id 0则代表当前 决定了此钩子是系统钩子还是线程钩子 //! 返回值 函数执行成功,则返回值就是该挂钩处理过程的句柄;若此函数执行失败,则返回值为NULL(0) g_hook = SetWindowsHookEx(WH_KEYBOARD_LL, Hookproc, nullptr, 0); } CHook::~CHook() {
// 卸载钩子 UnhookWindowsHookEx(g_hook); }
main.cpp
讯享网#include "CMainWindow.h" #include <QApplication> #include "CHook.h" CMainWindow *g_mainWdindow; int main(int argc, char *argv[]) {
QApplication a(argc, argv); // 创建钩子对象 CHook hook; // 创建程序对象 g_mainWdindow = new CMainWindow; // 初始化程序 g_mainWdindow->initialize(); int ret = a.exec(); // 反初始化 g_mainWdindow->uninitialize(); delete g_mainWdindow; return ret; }
总结
使用钩子时注意数据的类型及参数的含义,不同的钩子其参数及含义不同需要好好记一下;包括钩子可以封装在库中或子线程中调用,该部分文中没有体现,值得研究一下。

相关文章
Qt之QGraphicsView实现截图(漏洞百出且BUG丛生版,部分源码+注释)

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/69663.html