QT添加全局热键(windows平台)

Qt 提供了QShortcut来实现快捷键的功能,不过它的响应范围只局限于窗口内。如果脱离了进程窗口,如在桌面,或者正在使用其他软件,是无法响应的。

要解决这样的问题可以使用Windows 提供的API再结合qt的一些功能来实现一个全局可响应的快捷键。

直接行代码,首先在mai函数添加快捷绑定进行注册

	MyGlobalShortCut *shortcut = new MyGlobalShortCut("Ctrl+Down", &w);
	QObject::connect(shortcut, SIGNAL(activated()), &w, SLOT(rec_testShotCutAns()));

然后添加MyGlobalShortCut.h

// Qt 升级到5.x版本后
// QAbstractEventDispatcher 中函数发生变动
// 导致libqxt库中的qxtGlobalShortcut挂掉
// 参考qxtGlobalShortcut写了一个全局热键类
// 用法与qxtGlobalShortcut一致
// 在 Win8.1 + Qt5.11 下能正常使用
// by 迷路君 2014.03.27

#pragma once
#include <QApplication>
#include <windows.h>
#include <shotcut/MyWinEventFilter.h>
#include <QKeySequence>
#include <QHash>

class MyGlobalShortCut : public QObject
{
	Q_OBJECT
public:


	MyGlobalShortCut(QString key, QObject* app);
	~MyGlobalShortCut();
	void activateShortcut();
	bool registerHotKey();
	bool unregisterHotKey();
	QHash<QPair<quint32, quint32>, MyGlobalShortCut*> shortcuts;
private:
	QApplication *m_app;
	MyWinEventFilter *m_filter;
	QKeySequence m_key;
	Qt::Key key;
	Qt::KeyboardModifiers mods;
	static quint32 nativeKeycode(Qt::Key keycode);
	static quint32 nativeModifiers(Qt::KeyboardModifiers modifiers);
signals:
	void activated();

};

添加MyGlobalShortCut.cpp

#include "MyGlobalShortCut.h"

MyGlobalShortCut::~MyGlobalShortCut()
{
	unregisterHotKey();
}
MyGlobalShortCut::MyGlobalShortCut(QString key, QObject *app)
{
	m_key = QKeySequence(key);
	m_filter = new MyWinEventFilter(this);
	m_app->installNativeEventFilter(m_filter);


	registerHotKey();
}

void MyGlobalShortCut::activateShortcut()
{
	emit activated();
}
bool  MyGlobalShortCut::registerHotKey()
{
	Qt::KeyboardModifiers allMods = Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier;
	key = (m_key.isEmpty() ? Qt::Key(0) : Qt::Key((m_key[0] ^ allMods) & m_key[0]));
	mods = m_key.isEmpty() ? Qt::KeyboardModifiers(0) : Qt::KeyboardModifiers(m_key[0] & allMods);
	const quint32 nativeKey = nativeKeycode(key);
	const quint32 nativeMods = nativeModifiers(mods);

	shortcuts.insert(qMakePair(nativeKey, nativeMods), this);
	return RegisterHotKey(0, nativeMods ^ nativeKey, nativeMods, nativeKey);

}
bool  MyGlobalShortCut::unregisterHotKey()
{
	return UnregisterHotKey(0, (quint32)nativeModifiers(mods) ^ (quint32)nativeKeycode(key));
}
quint32 MyGlobalShortCut::nativeKeycode(Qt::Key key)
{
	switch (key)
	{
	case Qt::Key_Escape:
		return VK_ESCAPE;
	case Qt::Key_Tab:
	case Qt::Key_Backtab:
		return VK_TAB;
	case Qt::Key_Backspace:
		return VK_BACK;
	case Qt::Key_Return:
	case Qt::Key_Enter:
		return VK_RETURN;
	case Qt::Key_Insert:
		return VK_INSERT;
	case Qt::Key_Delete:
		return VK_DELETE;
	case Qt::Key_Pause:
		return VK_PAUSE;
	case Qt::Key_Print:
		return VK_PRINT;
	case Qt::Key_Clear:
		return VK_CLEAR;
	case Qt::Key_Home:
		return VK_HOME;
	case Qt::Key_End:
		return VK_END;
	case Qt::Key_Left:
		return VK_LEFT;
	case Qt::Key_Up:
		return VK_UP;
	case Qt::Key_Right:
		return VK_RIGHT;
	case Qt::Key_Down:
		return VK_DOWN;
	case Qt::Key_PageUp:
		return VK_PRIOR;
	case Qt::Key_PageDown:
		return VK_NEXT;
	case Qt::Key_F1:
		return VK_F1;
	case Qt::Key_F2:
		return VK_F2;
	case Qt::Key_F3:
		return VK_F3;
	case Qt::Key_F4:
		return VK_F4;
	case Qt::Key_F5:
		return VK_F5;
	case Qt::Key_F6:
		return VK_F6;
	case Qt::Key_F7:
		return VK_F7;
	case Qt::Key_F8:
		return VK_F8;
	case Qt::Key_F9:
		return VK_F9;
	case Qt::Key_F10:
		return VK_F10;
	case Qt::Key_F11:
		return VK_F11;
	case Qt::Key_F12:
		return VK_F12;
	case Qt::Key_F13:
		return VK_F13;
	case Qt::Key_F14:
		return VK_F14;
	case Qt::Key_F15:
		return VK_F15;
	case Qt::Key_F16:
		return VK_F16;
	case Qt::Key_F17:
		return VK_F17;
	case Qt::Key_F18:
		return VK_F18;
	case Qt::Key_F19:
		return VK_F19;
	case Qt::Key_F20:
		return VK_F20;
	case Qt::Key_F21:
		return VK_F21;
	case Qt::Key_F22:
		return VK_F22;
	case Qt::Key_F23:
		return VK_F23;
	case Qt::Key_F24:
		return VK_F24;
	case Qt::Key_Space:
		return VK_SPACE;
	case Qt::Key_Asterisk:
		return VK_MULTIPLY;
	case Qt::Key_Plus:
		return VK_ADD;
	case Qt::Key_Comma:
		return VK_SEPARATOR;
	case Qt::Key_Minus:
		return VK_SUBTRACT;
	case Qt::Key_Slash:
		return VK_DIVIDE;

		// numbers
	case Qt::Key_0:
	case Qt::Key_1:
	case Qt::Key_2:
	case Qt::Key_3:
	case Qt::Key_4:
	case Qt::Key_5:
	case Qt::Key_6:
	case Qt::Key_7:
	case Qt::Key_8:
	case Qt::Key_9:
		return key;

		// letters
	case Qt::Key_A:
	case Qt::Key_B:
	case Qt::Key_C:
	case Qt::Key_D:
	case Qt::Key_E:
	case Qt::Key_F:
	case Qt::Key_G:
	case Qt::Key_H:
	case Qt::Key_I:
	case Qt::Key_J:
	case Qt::Key_K:
	case Qt::Key_L:
	case Qt::Key_M:
	case Qt::Key_N:
	case Qt::Key_O:
	case Qt::Key_P:
	case Qt::Key_Q:
	case Qt::Key_R:
	case Qt::Key_S:
	case Qt::Key_T:
	case Qt::Key_U:
	case Qt::Key_V:
	case Qt::Key_W:
	case Qt::Key_X:
	case Qt::Key_Y:
	case Qt::Key_Z:
		return key;

	default:
		return 0;
	}
}
quint32 MyGlobalShortCut::nativeModifiers(Qt::KeyboardModifiers modifiers)
{
	// MOD_ALT, MOD_CONTROL, (MOD_KEYUP), MOD_SHIFT, MOD_WIN
	quint32 native = 0;
	if (modifiers & Qt::ShiftModifier)
		native |= MOD_SHIFT;
	if (modifiers & Qt::ControlModifier)
		native |= MOD_CONTROL;
	if (modifiers & Qt::AltModifier)
		native |= MOD_ALT;
	if (modifiers & Qt::MetaModifier)
		native |= MOD_WIN;
	// TODO: resolve these?
	//if (modifiers & Qt::KeypadModifier)
	//if (modifiers & Qt::GroupSwitchModifier)
	return native;
}

添加win事件MyWinEventFilter.h

#pragma once
#include <QAbstractNativeEventFilter>

class MyGlobalShortCut;

class MyWinEventFilter : public QAbstractNativeEventFilter
{
public:
	MyWinEventFilter(MyGlobalShortCut *shortcut);
	~MyWinEventFilter();
	virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *);
private:
	MyGlobalShortCut *m_shortcut;
};

以及MyWinEventFilter.cpp

#include <shotcut/MyWinEventFilter.h>
#include <shotcut/MyGlobalShortCut.h>


MyWinEventFilter::~MyWinEventFilter()
{

}

MyWinEventFilter::MyWinEventFilter(MyGlobalShortCut *shortcut)
	: m_shortcut(shortcut)
{

}


bool MyWinEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *)
{
	if (eventType == "windows_generic_MSG")
	{
		MSG *msg = static_cast<MSG *>(message);
		if (msg->message == WM_HOTKEY)
		{
			//            if(msg->wParam == VK_F10)
			//            {
			//               m_shortcut->activateShortcut();
			//               return true;
			//            }
			const quint32 keycode = HIWORD(msg->lParam);
			const quint32 modifiers = LOWORD(msg->lParam);
			bool res = m_shortcut->shortcuts.value(qMakePair(keycode, modifiers));
			if (res)
			{
				m_shortcut->activateShortcut();
				return true;
			}
		}

	}
	return false;
}

这样就可以了

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值