Qt实现全局快捷键功能利用QxtGlobalShortcut库

快捷键 Qt
0 378
suoniao 2021-03-31
需要:0索币

不少人有给程序添加全局热键的需求。网上随便一搜,就能找到不少介绍windows下如何实现的方式:

首先: 使用 RegisterHotKey和 UnregisterHotKey 注册和反注册热键

其次: 在事件全局过滤器 winEventFilter 中相应热键

但是涉及其他平台的,中文资料中提到的似乎不多。

libqxt

其实Qt第三方的库 libqxt 中已经给出了一个比较好的跨平台的解决方案,这就是 QxtGlobalShortcut。


所以,只要你使用这个第三方库就可以了。


可是,你会不会想,我仅仅为了使用这个类,而引入这个 libqxt 第三方库是不是有点大题小做?我能不能将其剥离出来单独使用?


QxtGlobalShortcut

恩,用google搜索一下,就可以知道,网上很多人都做过这个工作了。你会发现很多人将剥离出的 QxtGlobalShortcut 作为项目的 3rdparty 部分。


那么我们接下来就看看这个 QxtGlobalShortcut :


用法

已经简单到不能再简单了,是不?


QxtGlobalShortcut* shortcut = new QxtGlobalShortcut(QKeySequence("Ctrl+Shift+F12"), w);

connect(shortcut, SIGNAL(activated()), w, SLOT(myslot()));

注意:如果你对其内部实现不感兴趣,只关心如何使用,那么这个小例子可能就是你需要的全部了 :http://code.google.com/p/h-qt-exercise/downloads/detail?name=shortcut.zip&can=2&q=


源码文件

 

gxtglobal.h


libqxt 一个全局文件


*


qxtglobalshortcut.h


我们最关心的接口文件


 


qxtglobalshortcut_.h


私有头文件


 

gxtglobalshortcut.cpp


类的实现(平台无关部分)


 

gxtglobalshortcut_win.cpp


类的实现(win)


 

gxtglobalshortcut_x11.cpp


类的实现(x11)


 

gxtglobalshortcut_mac.cpp


类的实现(mac)


热键的注册过程

我们通过构造函数,或者setShortcut 成员设置一个热键时:


首先将这个 QKeySequence 分解成两部分 Qt::Key 和 Qt::KeyboardModifiers


(即:下面的 key 和 mods)

然后,key 和 mods 分别转换成平台相关(native)的码值,并调用平台相关的函数进行注册

最后,将key与mods的native码值构成的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().

然后我们在过滤器中分别进行处理,比如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是平台无关的:


void QxtGlobalShortcutPrivate::activateShortcut(quint32 nativeKey, quint32 nativeMods)

{

    QxtGlobalShortcut* shortcut = shortcuts.value(qMakePair(nativeKey, nativeMods));

    if (shortcut && shortcut->isEnabled())

        emit shortcut->activated();

}

记得前面注册热键是保存东西到一个QHash么?它是在这儿起作用的,当一个热键到来时,我们从该QHash查找有没有相应的QxtGlobalShortcut存在,存在且启用的话,则发射信号。


如何使用

为了便于使用,我们可以在这个文件的同级目录中添加一个 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

这样一来,当我们使用时,只需要在我们的pro文件内多加一行:


include(yourpath/qxtglobalshortcut.pri)

即可


一个具体的小例子:http://code.google.com/p/h-qt-exercise/downloads/detail?name=shortcut.zip&can=2&q=


参考

http://libqxt.bitbucket.org/doc/tip/qxtglobalshortcut.html


http://software.intel.com/zh-cn/articles/jason_lee20100430/


http://www.cuteqt.com/blog/?p=2088

————————————————

原文链接:https://blog.csdn.net/dbzhang800/article/details/6302816

回帖
  • 消灭零回复
相关主题
QListWidget滚动的时候显示不完整 滚动条模式导致的哦 0
Qt设置顶层面板背景透明Qt::WA_TranslucentBackground 隐藏边框Qt::FramelessWindowHint 0
QCheckBox的QSS样式表总结 0
Qt通过qRegisterMetaType注册自定义数据类型 0
QListwidget触发2次itemClicked事件 0
Qt利用QLabel组件来显示图片 0
TableView自定义代理QStyledItemDelegate实现ComboBox 0
Qt利用QGraphicsView类实现图片放大缩小平移显示 0
Qt实现非阻塞延迟方法sleep 0
Qt实现webdav客户端功能支持https协议的webdav客户端 0
Qt操作windows注册表的方法 bat从注册表中将键值删除 0
重写QSqlQueryModel实现QTableView显示图片 0
QLocalServer基于本地套接字socket的服务端server 0
Qt使用动态库的方法 QLibrary库的典型用法 0
QT实现视频播放器界面开发 0
QTableview实现鼠标放上面显示不同颜色 0
Qt的QTableView自定义委托详解 0
QTableView利用自定义委托实现日期显示下拉菜单文字颜色等 0
Qt利用QApplication::sendEvent和QMouseEvent模拟鼠标点击事件 0
Qt获取父进程路径和父进程ID代码 0
相关主题
QListWidget滚动的时候显示不完整 滚动条模式导致的哦 0
Qt设置顶层面板背景透明Qt::WA_TranslucentBackground 隐藏边框Qt::FramelessWindowHint 0
QMenu和QMenuBar样式表大全 qss 0
QT定时器startTimer和timerEvent事件 每隔interval 毫秒就会启动一次 0
C语言内存分配函数malloc和calloc的区别 0
QCheckBox的QSS样式表总结 0
Qt通过qRegisterMetaType注册自定义数据类型 0
QListwidget触发2次itemClicked事件 0
打印机USB驱动开发之实现打印服务器 0
Qt利用QLabel组件来显示图片 0
TableView自定义代理QStyledItemDelegate实现ComboBox 0
Qt利用QGraphicsView类实现图片放大缩小平移显示 0
Qt实现非阻塞延迟方法sleep 0
海康相机SDK的C++对应的接口 0
Qt实现webdav客户端功能支持https协议的webdav客户端 0
CHKDSK解决 移动硬盘只能看见盘符其它信息都看不见另外双击也打不开 0
gogs一直报errror:dial tcp xxx.xxx.xxx.xxx 宿主机的ip 0
索鸟快传2.1.2发布 0
索鸟快传2.1.1发布 0
Qt操作windows注册表的方法 bat从注册表中将键值删除 0