QT全局钩子监控鼠标和键盘

1、前言

      想要在窗口失去焦点的情况下获取鼠标和键盘消息,需要用到钩子技术,API函数为:SetWindowsHookEx()。而且必须是全局钩子,全局钩子需要使用DLL注入。即首先生成一个带有全局钩子的DLL,DLL获取鼠标位置和键盘按键消息再发送给QT主程序。

2、全局钩子DLL

// myHookMouseAndKeybord.cpp : 定义 DLL 应用程序的导出函数。
//
#include <windows.h>
#include "stdafx.h"

//HINSTANCE g_hInstance;
HHOOK g_hMouseHook;
HHOOK g_hKeybordHook;
HWND g_hMainWND;
//安装鼠标钩子(要生成lib文件需要加上extern "C" __declspec(dllexport) )
extern "C" __declspec(dllexport) BOOL InstallMouseHook(HWND hWnd);
//卸载鼠标钩子
extern "C" __declspec(dllexport) BOOL UnInstallMouseHook();
//安装键盘钩子
extern "C" __declspec(dllexport) BOOL InstallKeybordHook();
//卸载键盘钩子
extern "C" __declspec(dllexport) BOOL UnInstallKeybordHook();

//鼠标钩子处理函数声明
LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam);
//键盘钩子处理函数声明
LRESULT CALLBACK keyBordProc(int nCode, WPARAM wParam, LPARAM lParam);

//安装鼠标钩子
BOOL InstallMouseHook(HWND hWnd)
{
	g_hMouseHook = SetWindowsHookEx(WH_MOUSE_LL, MouseProc, GetModuleHandle(L"myHookMouseAndKeybord"), 0);
	g_hMainWND = hWnd;
	if (g_hMouseHook != NULL)
	{
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}

//卸载鼠标钩子
BOOL UnInstallMouseHook()
{
	return UnhookWindowsHookEx(g_hMouseHook);
}


//安装键盘钩子
BOOL InstallKeybordHook()
{
	g_hKeybordHook = SetWindowsHookEx(WH_KEYBOARD_LL, keyBordProc, GetModuleHandle(L"myHookMouseAndKeybord"), 0);
	if (g_hKeybordHook != NULL)
	{
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}

//卸载键盘钩子
BOOL UnInstallKeybordHook()
{
	return UnhookWindowsHookEx(g_hKeybordHook);
}

//鼠标钩子处理函数
LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
	if (wParam == WM_RBUTTONDOWN) //当鼠标点击右键时发送信息给QT主窗口
	{

		MOUSEHOOKSTRUCT *mhookstruct;   //鼠标HOOK结构体
		mhookstruct = (MOUSEHOOKSTRUCT*)lParam;
		POINT pt = mhookstruct->pt;  //将当前鼠标坐标点的x,y坐标作为参数向主程序窗口发送消息
		PostMessage(g_hMainWND, WM_RBUTTONDOWN, MK_CONTROL, MAKELPARAM(pt.x, pt.y));
	}
	return CallNextHookEx(g_hMouseHook, nCode, wParam, lParam);
}

//键盘钩子处理函数
LRESULT CALLBACK keyBordProc(int nCode, WPARAM wParam, LPARAM lParam)
{
	if (wParam == WM_KEYDOWN)
	{
		tagKBDLLHOOKSTRUCT *keyhookstruct;   //键盘HOOK结构体
		keyhookstruct = (tagKBDLLHOOKSTRUCT*)lParam;
		PostMessage(g_hMainWND, WM_KEYDOWN, keyhookstruct->vkCode, keyhookstruct->scanCode);
	}

	return CallNextHookEx(g_hKeybordHook, nCode, wParam, lParam);
}

3、发送鼠标键盘消息

      上面代码已经贴出来了,就在钩子处理函数中。鼠标发送的是位置信息,键盘发送的是键码

4、QT窗口接收信息

QT要接收消息,需要在QApplication中安装QAbstractNativeEventFilter,

#include "LOLdesk.h"
#include <QtWidgets/QApplication>
#include <QAbstractNativeEventFilter>
#include <QDebug>

class MyAppNativeEventFilter : public QAbstractNativeEventFilter
{
	virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *longMsg) override
	{
		if (eventType == "windows_generic_MSG" || eventType == "windows_dispatcher_MSG")
		{
			MSG* pMsg = reinterpret_cast<MSG*>(message);
			if (pMsg->message == WM_RBUTTONDOWN)
			{
				POINT pt = pMsg->pt;
				qDebug() << "x="<<pt.x << "y=" << pt.y;
			}
			if (pMsg->message == WM_KEYDOWN)
			{
				qDebug() << pMsg->wParam;
			}
		}
		return false; // 注意返回值
	};

};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    LOLdesk w;
	MyAppNativeEventFilter filter;
	a.installNativeEventFilter(&filter); //在APP上安装EventFilter
    w.show();
    return a.exec();
}

5、调用DLL钩子

//链接lib文件
#pragma  comment(lib, "myHookMouseAndKeybord.lib") 
//安装鼠标钩子声明
extern "C" __declspec(dllimport) BOOL InstallMouseHook(HWND hWnd);
//卸载鼠标钩子声明
extern "C" __declspec(dllimport) BOOL UnInstallMouseHook();
//安装键盘钩子
extern "C" __declspec(dllimport) BOOL InstallKeybordHook();
//卸载键盘钩子
extern "C" __declspec(dllimport) BOOL UnInstallKeybordHook();

//安装钩子
BOOL LOLdesk::installHook()
{
	HMODULE hDll = NULL;
	HWND m_hWnd = (HWND)this->winId();
	BOOL hookMouseState = InstallMouseHook(m_hWnd);
	BOOL hookKeybordState = InstallKeybordHook();
	if (!hookMouseState && !hookKeybordState)
	{
		qDebug() << "hook failed!";
	}
	else
	{
		qDebug() << "hook success!";
	}
	return 0;
}

//卸载钩子
BOOL LOLdesk::uninstallHook()
{
	BOOL hookMouseState = UnInstallMouseHook();
	BOOL hookKeybordState = UnInstallKeybordHook();
	if (!hookMouseState && !hookKeybordState)
	{
		qDebug() << "unhook failed!";
	}
	else
	{
		qDebug() << "unhook success!";
	}
	return 0;
}
  • 4
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
QT 中,可以使用事件过滤器来监控鼠标键盘操作。事件过滤器是 QT 中的一个重要机制,可以在一个对象中拦截和处理其他对象发送的事件。例如,在一个 QWidget 对象中,可以安装一个事件过滤器,来监视其他对象发送的事件。 下面是一个示例代码,用于在 QT监控鼠标键盘操作: ```cpp #include <QApplication> #include <QEvent> #include <QMouseEvent> #include <QKeyEvent> #include <QDebug> class EventFilter : public QObject { public: EventFilter(QObject* parent = nullptr) : QObject(parent) { } protected: bool eventFilter(QObject* obj, QEvent* event) override { if (event->type() == QEvent::MouseButtonPress) { QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event); qDebug() << "鼠标按下:" << mouseEvent->button() << ",位置:" << mouseEvent->pos(); } else if (event->type() == QEvent::KeyPress) { QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event); qDebug() << "按键按下:" << keyEvent->key(); } return QObject::eventFilter(obj, event); } }; int main(int argc, char *argv[]) { QApplication a(argc, argv); // 创建一个 QWidget 对象,并安装事件过滤器 QWidget widget; EventFilter eventFilter(&widget); widget.installEventFilter(&eventFilter); widget.show(); return a.exec(); } ``` 在上面的代码中,我们创建了一个 EventFilter 类,继承自 QObject,用于作为事件过滤器。在 eventFilter 方法中,我们判断事件的类型,如果是鼠标按下事件,就打印鼠标的按键和位置信息;如果是按键按下事件,就打印按键的键码。 然后,在 main 函数中,我们创建了一个 QWidget 对象,并安装了上面创建的事件过滤器。当用户在这个 QWidget 对象中进行鼠标键盘操作时,事件会先发送到事件过滤器中,被拦截和处理。 当然,如果你需要在整个应用程序中监控鼠标键盘操作,你可以在 QApplication 对象中安装事件过滤器。
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值