詳解 Qt 全局熱鍵 QxtGlobalShortcut 分析與使用舉例
Qt 全局熱鍵 QxtGlobalShortcut 分析與使用舉例,與你分享,如果你需要全局熱鍵,那么本文將會為你解決。
首先: 使用 RegisterHotKey和 UnregisterHotKey 注冊和反注冊熱鍵
其次: 在事件全局過濾器 winEventFilter 中相應(yīng)熱鍵,但是涉及其他平臺的,中文資料中提到的似乎不多。
libqxt
其實Qt第三方的庫 libqxt 中已經(jīng)給出了一個比較好的跨平臺的解決方案,這就是 QxtGlobalShortcut。
所以,只要你使用這個第三方庫就可以了。
可是,你會不會想,我僅僅為了使用這個類,而引入這個 libqxt 第三方庫是不是有點大題小做?我能不能將其剝離出來單獨使用?
QxtGlobalShortcut
恩,用google搜索一下,就可以知道,網(wǎng)上很多人都做過這個工作了。你會發(fā)現(xiàn)很多人將剝離出的 QxtGlobalShortcut 作為項目的 3rdparty 部分。
那么我們接下來就看看這個 QxtGlobalShortcut :
用法
已經(jīng)簡單到不能再簡單了,是不?
- QxtGlobalShortcut* shortcut = new QxtGlobalShortcut(QKeySequence("Ctrl+Shift+F12"), w);
connect(shortcut, SIGNAL(activated()), w, SLOT(myslot()));注意:如果你對其內(nèi)部實現(xiàn)不感興趣,只關(guān)心如何使用,那么這個小例子可能就是你需要的全部了 :
http://code.google.com/p/h-qt-exercise/downloads/detail?name=shortcut.zip&can=2&q=
源碼文件
- gxtglobal.h
libqxt 一個全局文件
- qxtglobalshortcut.h
我們最關(guān)心的接口文件
- qxtglobalshortcut_.h
私有頭文件
- gxtglobalshortcut.cpp
類的實現(xiàn)(平臺無關(guān)部分)
- gxtglobalshortcut_win.cpp
類的實現(xiàn)(win)
- gxtglobalshortcut_x11.cpp
類的實現(xiàn)(x11)
- gxtglobalshortcut_mac.cpp
類的實現(xiàn)(mac)
熱鍵的注冊過程
我們通過構(gòu)造函數(shù),或者setShortcut 成員設(shè)置一個熱鍵時:
首先將這個 QKeySequence 分解成兩部分 Qt::Key 和 Qt::KeyboardModifiers
(即:下面的 key 和 mods)
然后,key 和 mods 分別轉(zhuǎn)換成平臺相關(guān)(native)的碼值,并調(diào)用平臺相關(guān)的函數(shù)進(jìn)行注冊
最后,將key與mods的native碼值構(gòu)成的QPair作為QHash的鍵,將該shortcut的指針作為值保存起來。
- bool QxtGlobalShortcutPrivate::setShortcut(const QKeySequence& shortcut)
- {
- ...
- key = ...
- mods = ...
- const quint32 nativeKey = nativeKeycode(key);
- const quint32 nativeMods = nativeModifiers(mods);
- const bool res = registerShortcut(nativeKey, nativeMods);
- shortcuts.insert(qMakePair(nativeKey, nativeMods), &qxt_p());
反注冊的過程與此類似。
熱鍵激活
首先給 QAbstractEventDispatcher 安裝事件過濾器
- QAbstractEventDispatcher::instance()->setEventFilter(eventFilter);注意,這兒不是給 QApplication 安裝的。Manual中是這樣告訴我們的
- bool QCoreApplication::winEventFilter ( MSG * msg, long * result ) [virtual]
- To handle system wide messages, such as messages from a registered hot key,
- you need to install an event filter on the event dispatcher,
- which is returned from QAbstractEventDispatcher::instance().然后我們在過濾器中分別進(jìn)行處理,比如windows下
- bool QxtGlobalShortcutPrivate::eventFilter(void* message)
- {
- MSG* msg = static_cast<MSG*>(message);
- if (msg->message == WM_HOTKEY){
- const quint32 keycode = HIWORD(msg->lParam);
- const quint32 modifiers = LOWORD(msg->lParam);
- activateShortcut(keycode, modifiers);
- }
- return false;
- }
- 或 x11 下:
- bool QxtGlobalShortcutPrivate::eventFilter(void* message)
- {
- XEvent* event = static_cast<XEvent*>(message);
- if (event->type == KeyPress){
- XKeyEvent* key = (XKeyEvent*) event;
- activateShortcut(key->keycode, key->state & (ShiftMask | ControlMask | Mod1Mask | Mod4Mask));
- }
- return false;
- }
其中activateShortcut是平臺無關(guān)的:
- void QxtGlobalShortcutPrivate::activateShortcut(quint32 nativeKey, quint32 nativeMods)
- {
- QxtGlobalShortcut* shortcut = shortcuts.value(qMakePair(nativeKey, nativeMods));
- if (shortcut && shortcut->isEnabled())
- emit shortcut->activated();
- }
記得前面注冊熱鍵是保存東西到一個QHash么?它是在這兒起作用的,當(dāng)一個熱鍵到來時,我們從該QHash查找有沒有相應(yīng)的QxtGlobalShortcut存在,存在且啟用的話,則發(fā)射信號。
如何使用
為了便于使用,我們可以在這個文件的同級目錄中添加一個 qxtglobalshortcut.pri 的文件:
- INCLUDEPATH += $$PWD
- DEPENDPATH += $$PWD
- HEADERS += $$PWD/qxtglobal.h \
- $$PWD/qxtglobalshortcut.h \
- $$PWD/qxtglobalshortcut_p.h
- SOURCES += $$PWD/qxtglobalshortcut.cpp
- win32{
- SOURCES += $$PWD/qxtglobalshortcut_win.cpp
- LIBS += -luser32
- }
- unix:SOURCES += $$PWD/qxtglobalshortcut_x11.cpp
- mac:SOURCES += $$PWD/qxtglobalshortcut_mac.cpp
這樣一來,當(dāng)我們使用時,只需要在我們的pro文件內(nèi)多加一行:
include(yourpath/qxtglobalshortcut.pri)即可
一個具體的小例子:http://code.google.com/p/h-qt-exercise/downloads/detail?name=shortcut.zip&can=2&q=
小結(jié):Qt 全局熱鍵 QxtGlobalShortcut 分析與使用舉例的內(nèi)容為大家介紹完了,希望你幫你解決問題。