一、后台钩子截图调用示例
二、钩子的个人理解
- 挂接钩子的步骤: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丛生版,部分源码+注释)
友情提示——哪里看不懂可私哦,让我们一起互相进步吧
(创作不易,请留下一个免费的赞叭 谢谢 o/)
注:文章为作者编程过程中所遇到的问题和总结,内容仅供参考,若有错误欢迎指出。
注:如有侵权,请联系作者删除