Реклама

Qt WinAPI - Урок 005. Глобальный HotKey WinAPI в Qt 5

Qt, HotKey, RegisterHotKey, UnregisterHotKey, WinAPI, горячие клавиши

Для работы с глобальными 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
}

Итог

В результате работы данного программного кода будет производиться обработка глобального сочетания горячих клавиш даже в том случае, если окно приложения будет скрыто в лоток системного трея. Демонстрацию работы приложения можно увидеть в видеоуроке.

Видеоурок

Реклама

Комментарии

Комментарии

Только авторизованные пользователи могут оставлять комментарии.
Пожалуйста, Авторизуйтесь или Зарегистрируйтесь
  • BlinCT
  • 22 октября 2017 г. 12:46

C++ - Тест 003. Условия и циклы

  • Результат 64 баллов
  • Очки рейтинга -1
  • Kiops
  • 22 октября 2017 г. 3:56

C++ - Тест 001. Первая программа и типы данных

  • Результат 86 баллов
  • Очки рейтинга 6
  • Kiops
  • 22 октября 2017 г. 2:41

Qt - Тест 001. Сигналы и слоты

  • Результат 100 баллов
  • Очки рейтинга 10
Последние комментарии
  • EVILEG
  • 21 октября 2017 г. 3:06

Qt/C++ - Урок 031. QCustomPlot - строим график по времени

Добавил архив с проектом

  • EVILEG
  • 20 октября 2017 г. 20:06

Qt/C++ - Урок 031. QCustomPlot - строим график по времени

После работы поищу, должен где-то быть на винте.

  • Миша
  • 20 октября 2017 г. 20:04

Qt/C++ - Урок 031. QCustomPlot - строим график по времени

не могли бы вы выложить архив с рабочей версией скрипта?

  • EVILEG
  • 20 октября 2017 г. 20:03

Qt/C++ - Урок 030. QCustomPlot - быстрый старт в работе с графиками

Использование дизайнера в Qt Creator и использование ui файлов является распространённой практикой в Qt фреймворке. Написать отдельную статью про то, что это такое? - может быть. Опи...

  • Миша
  • 20 октября 2017 г. 19:43

Qt/C++ - Урок 030. QCustomPlot - быстрый старт в работе с графиками

Но почему вы это не описали? Не могли бы вы описать.

Сейчас обсуждают на форуме
  • EVILEG
  • 22 октября 2017 г. 12:05

Закрепление якорей в момент создания объекта через JS

Добрый день! Якоря - это не те свойства, которые можно устанавливать сразу по инициализации, лучше их править после создания объекта, поскольку при одновременной установке они могут в...

  • EVILEG
  • 21 октября 2017 г. 23:33

Создание истории редактирования постов на сайте

Ясно. Тогда я лучше не буду тратить время на его проверку. Тем более, что я использую гугловский prettyprint для подсветки кода. Спасибо за информацию.

QFile::copy() возвращает false

Получилось! Спасибо огромное! path1 = "C:/Users/555/Pictures/00GAF13AP001-002.jpg"true

  • cordsac
  • 19 октября 2017 г. 15:49

How can I select the QGraphicView Item and change the properties

Ok I'll check it sir,If you can please do article(tutorial) about this,Its really useful.Thank you if you can give me some sample code when you free.thanks again

  • cordsac
  • 17 октября 2017 г. 19:28

How can I open SVG file through QT

Okay,Thank you sir :)