Для работы с глобальными HotKey в Qt 5 присутствует виртуальный метод nativeEvent . Данный метод заменил методы winEvent , x11Event , macEvent из Qt 4.8.
Фишка в работе HotKey с Qt заключается в том, что если окно находится не в фокусе, то есть оно, например, будет свёрнуто в системный трей, то тогда зарегистрированные QShortcut работать просто не будут. Поэтому необходимо работать с глобальными событиями от операционной системы, то есть перейти к реализации платформозависимой части кода в приложении на Qt.
RegisterHotKey
В данном примере разберём вариант работы с WinAPI . Для этого воспользуемся функцией RegisterHotKey.
- BOOL WINAPI RegisterHotKey(
- _In_opt_ HWND hWnd,
- _In_ int id,
- _In_ UINT fsModifiers,
- _In_ UINT vk
- );
Параметры RegisterHotKey
hWnd [in, optional]
Тип:
HWND
Обработчик окна, которое будет принимать сообщения
WM_HOTKEY
, которые будут генерироваться горячей клавишей.
id [in]
Тип:
int
Идентификатор горячих клавиш. Если
hWnd
параметр является NULL, тогда горячие клавиши ассоциируются с текущим потоком, а не с конкретным окном.
fsModifiers [in]
Тип:
UINT
Клавиши модификаторы, которые должны быть нажаты в сочетании с указанной клавишей в
uVirtKey
параметре для создания сообщения
WM_HOTKEY.
fsModifiers
параметр может быть комбинацией следующих значений.
- MOD_ALT 0x0001 - Должна удерживаться клавиша ALT;
- MOD_CONTROL 0x0002 - Должна удерживаться клавиша CTRL;
- MOD_NOREPEAT 0x4000 - Изменяет поведение HotKey, чтобы клавиатура не генерировала несколько сообщений HotKey. В Windows Vista данный флаг не поддерживается.
- MOD_SHIFT 0x0004 - Должна удерживаться клавиша SHIFT;
- MOD_WIN 0x0008 - Должна удерживаться клавиша WINDOWS. Это клавиша с логотипом Windows.
vk [in]
Тип:
UINT
Код виртуальных клавиш для HotKey.
UnregisterHotKey
Отключение сочетания горячих клавиш.
- BOOL WINAPI UnregisterHotKey(
- _In_opt_ HWND hWnd,
- _In_ int id
- );
Параметры UnregisterHotKey
hWnd [in, optional]
Тип:
HWND
Обработчик окна ассоциированный с горячей клавишей, который должен быть освобождён. Этот параметр должен быть NULL, если не ассоциирован с окном.
id [in]
Тип:
int
Идентификатор сочетания горячих клавиш, который должен быть освобождён.
Пример работы с HotKey в WinAPI
Создадим проект для работы с HotKey. В данном проекте будет присутствовать объект класса QSystemTrayIcon. Будем скрывать приложение в системный трей и проверять сочетание горячих клавиш. Таким сочетанием будет "ALT+SHIFT+D" , например. В данном проекте обработчиком горячих клавиш будет MainWindow. Обработка сочетания горячих клавиш будет производиться в nativeEvent.
Проверку на сочетание выбранных горячих клавиш будем производить с помощью qDebug().
mainwindow.h
- #ifndef MAINWINDOW_H
- #define MAINWINDOW_H
- #include <QMainWindow>
- #include <QSystemTrayIcon>
- #include "windows.h" // Подключаем библиотеку WinAPI
- namespace Ui {
- class MainWindow;
- }
- class MainWindow : public QMainWindow
- {
- Q_OBJECT
- public:
- explicit MainWindow(QWidget *parent = 0);
- ~MainWindow();
- protected:
- // Метод для обработки native событий от ОС в Qt
- bool nativeEvent(const QByteArray &eventType, void *message, long *result);
- private slots:
- void iconActivated(QSystemTrayIcon::ActivationReason reason);
- private:
- Ui::MainWindow *ui;
- QSystemTrayIcon *trayIcon;
- };
- #endif // MAINWINDOW_H
mainwindow.cpp
- #include "mainwindow.h"
- #include "ui_mainwindow.h"
- #include <QDebug>
- MainWindow::MainWindow(QWidget *parent) :
- QMainWindow(parent),
- ui(new Ui::MainWindow)
- {
- ui->setupUi(this);
- /* Иконка системного трея нужна для того, чтобы
- * окно приложения было не в фокусе
- * */
- trayIcon = new QSystemTrayIcon(this);
- trayIcon->setIcon(this->style()->standardIcon(QStyle::SP_ComputerIcon));
- trayIcon->show();
- connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
- this, SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
- // Регистрируем HotKey "ALT+SHIFT+D"
- RegisterHotKey((HWND)MainWindow::winId(), // Устанавливаем системный идентификатор окна виджета, который будет обрабатывать HotKey
- 100, // Устанавливаем идентификатор HotKey
- MOD_ALT | MOD_SHIFT, // Устанавливаем модификаторы
- 'D'); // Определяем Горячую Клавишу для HotKey
- }
- MainWindow::~MainWindow()
- {
- delete ui;
- }
- bool MainWindow::nativeEvent(const QByteArray &eventType, void *message, long *result)
- {
- Q_UNUSED(eventType)
- Q_UNUSED(result)
- // Преобразуем указатель message в MSG WinAPI
- MSG* msg = reinterpret_cast<MSG*>(message);
- // Если сообщение является HotKey, то ...
- if(msg->message == WM_HOTKEY){
- // ... проверяем идентификатор HotKey
- if(msg->wParam == 100){
- // Сообщаем об этом в консоль
- qDebug() << "HotKey worked";
- return true;
- }
- }
- return false;
- }
- void MainWindow::iconActivated(QSystemTrayIcon::ActivationReason reason)
- {
- switch (reason){
- case QSystemTrayIcon::Trigger:
- !isVisible() ? show() : hide();
- break;
- default:
- break;
- }
- }
Примечание
Для того, чтобы проект скомпилировался с комплектом сборки MSVC, добавьте в pro файл проекта следующие строки:
- win32-msvc*{
- LIBS += -luser32
- }
Итог
В результате работы данного программного кода будет производиться обработка глобального сочетания горячих клавиш даже в том случае, если окно приложения будет скрыто в лоток системного трея. Демонстрацию работы приложения можно увидеть в видеоуроке.