Qt之Hook(键盘钩子)的简单使用(挂接截图程序,含源码+注释)

一、后台钩子截图调用示例

在这里插入图片描述

二、钩子的个人理解

  1. 挂接钩子的步骤: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);
  1. 各个类型的钩子原型一致,如下:
	/**
	 * @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)
  1. 不同的钩子对应的数据结构体及参数含义不同,如当关联键盘钩子(WH_KEYBOARD_LL)时,其lParam参数代表的结构体为KBDLLHOOKSTRUCT;当关联鼠标钩子(WH_MOUSE_LL)时,其wParam代表鼠标操作的类型(如左键按下、放开等),lParam参数代表的结构体为MSLLHOOKSTRUCT。具体可按需求查看对应内容。
  2. 推荐的链接:官方链接钩子(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/)

注:文章为作者编程过程中所遇到的问题和总结,内容仅供参考,若有错误欢迎指出。
注:如有侵权,请联系作者删除

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lw向北.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值