Qt 全局热键 QxtGlobalShortcut 分析与使用举例

转载 2012年03月29日 16:20:43

不少人有给程序添加全局热键的需求。网上随便一搜,就能找到不少介绍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)

即可

C#全局热键设置与窗体热键设置实例

1、窗体热键 首先要设置主窗体KeyPreview为true,可直接在属性中进行设置, 或者在窗体加载中设置: this.KeyPreview = true; 然后添加窗体KeyDown事件,如...
  • cuoban
  • cuoban
  • 2016年02月26日 16:16
  • 3386

MFC实现全局热键

要想使用全局热键的话,需要用到两个函数: BOOL WINAPI RegisterHotKey( __in_opt HWND hWnd, __in int id, __...
  • ccfxue
  • ccfxue
  • 2016年05月10日 16:53
  • 1117

Windows编程实现自定义全局热键

一、实现全局热键主要使用以下API(详情查看MSDN):- 获取热键标识:GlobalAddAtom - 注册热键:RegisterHotKey - 注销热键:UnregisterHotKey - 释...
  • zhoufuxinzfx
  • zhoufuxinzfx
  • 2016年03月09日 16:22
  • 2840

如何实现全局热键

要实现系统范围内的热键
  • wwkaven
  • wwkaven
  • 2014年06月14日 12:39
  • 2286

章鱼哥出品—VB.NET 自定义快捷键使用详解之全局热键

如何设置VB.NET 窗体的全局热键(快捷键),
  • zhangyubishoulin
  • zhangyubishoulin
  • 2014年10月06日 01:49
  • 4204

QT中监控全局键盘鼠标事件

现在我们新建一个类globalapp 继承QApplication,并重载notify函数,示例如下: globalapp.h #ifndef GLOBALAPP_H #define GLOBALAP...
  • chenyulancn
  • chenyulancn
  • 2016年04月29日 15:56
  • 1460

C#实现全局快捷键(系统热键)响应(转)

在应用中,我们可能会需要实现像Ctrl+C复制、Ctrl+V粘贴这样的快捷键,本文简单介绍了它的实现,并给出了一个实现类。 (1)建立一个类文件,命名为HotKey.cs,代码如下:...
  • zxj19951029
  • zxj19951029
  • 2014年10月18日 23:43
  • 457

QT如何捕获全局的键盘事件?

QT如何捕获全局的键盘事件? 方法一:继承QApplication类,并重载notify()函数 Qt是用QApplication::notify()函数来分发事件的。想要在任何事件过滤器查看任何...
  • CPeasant_Eva
  • CPeasant_Eva
  • 2015年01月26日 21:03
  • 3287

Delphi使用全局快捷键

Delphi使用全局快捷键 unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Gra...
  • gjtao1130
  • gjtao1130
  • 2013年08月08日 14:18
  • 2410

windows 设置全局快捷键;

简单设置全局快捷键: 组合键win+R 打开控制面板,小图表显示下 点击 管理工具项, 将自己想要谁知快捷键的程序的快捷方式放进去,(需要确认管理员权限) 如图,第...
  • csdn_Joker
  • csdn_Joker
  • 2016年11月27日 16:09
  • 4219
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Qt 全局热键 QxtGlobalShortcut 分析与使用举例
举报原因:
原因补充:

(最多只允许输入30个字)