Qt WinAPI - Урок 006. Разбор QKeySequence для RegisterHotKey в WinAPI

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

QKeySequence сильно отличается от последовательности горячих клавиш в WinAPI. QKeySequence фактически является строкой, в которой разделителем горячих клавиш являются знак "+" , а также последовательность ", " в случае, если последовательностей несколько. Тогда, как в WinAPI имеются модификаторы Alt, Ctrl, Shift, которые представлены беззнаковым целочисленным типом, и горячей клавишей, которая представлена кодом клавиатуры.

Разберём вариант, когда имеется одна последовательность в QKeySequence и её необходимо зарегистрировать в качестве глобальной горячей клавиши в WinAPI. Для этого условимся, что QKeySequence в качестве в качестве модификатора будет иметь лишь клавиши Ctrl, Alt, Shift и в качестве горячей клавиши одну из букв английского алфавита.

Далее для разбора QKeySequence напишем две функции:

  • unsigned int winKeyMod(QKeySequence) - которая будет возвращать целочисленную комбинацию модификаторов;
  • char winHotKey(QKetSequence) - которая будет возвращать код горячей клавиши.

Модификаторы Alt, Ctrl и Shift в битовом варианте имеют значения 0b00000001, 0b00000010 и 0b00000100 соответственно, поэтому логическое ИЛИ либо сложение данных чисел даст необходимое число комбинации. Следовательно необходимо в методе winKeyMod, выделить модификаторы из последовательности и в случае их наличия прибавить к числу модификатора, которое вернёт данный метод.

А winHotKey вернёт код горячей клавиши в виде переменной char. А выделен код клавиши будет в качестве кода UNICODE.

В статье о глобальных горячий клавиша х в WinAPI уже рассказывалось, что обработка производится в методе nativeEvent, поэтому не будем затягивать с этим вопросом и перейдём непосредственно к листингу кода.

Разбор QKeySequence

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QKeySequence>
#include <windows.h>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

protected:
    bool nativeEvent(const QByteArray &eventType, void *message, long *result);

private:
    Ui::MainWindow *ui;
    unsigned int winKeyMod(QKeySequence sequence);
    char winHotKey(QKeySequence sequence);
};

#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);

    // Зададим последовательность горячих клавиш
    QKeySequence keySequence(Qt::CTRL + Qt::ALT + Qt::SHIFT + 'A');

    /* Разрегистрируем последовательность с Id 100,
     * в примере не обязательно, но полезно для функции изменения HotKey
     * */
    UnregisterHotKey((HWND) MainWindow::winId(), 100);
    // Регистрируем HotKey
    RegisterHotKey((HWND)MainWindow::winId(),   // Id окна обработчика событий
                   100,                         // Id хоткея
                   winKeyMod(keySequence),      // Разбираем модификаторы из QKeySequence
                   winHotKey(keySequence));     // Выделяем горячую клавишу в последовательности
}

MainWindow::~MainWindow()
{
    delete ui;
}

/* Модификаторы в WinAPI представляют собой комбинацию целочисленных значений.
 * Поэтому возвращаем суммированное безнаковое число для установки модификатора
 * */
unsigned int MainWindow::winKeyMod(QKeySequence sequence)
{
    QStringList list = sequence.toString().split("+");
    unsigned int keyModificator = 0;

    // Проходим по QStringList и проверяем на наличие модификаторов
    foreach (QString str, list) {
        if(str == "Ctrl"){
            keyModificator += MOD_CONTROL;  // 0x0002
            continue;
        } else if(str == "Alt"){
            keyModificator += MOD_ALT;      // 0x0001
            continue;
        } else if(str == "Shift"){
            keyModificator += MOD_SHIFT;    // 0x0004
            continue;
        }
    }
    // В данном примере вернём
    return keyModificator; // 0b00000111 или 7
}

// Выделяем горячую клавишу из последовательности
char MainWindow::winHotKey(QKeySequence sequence)
{
    QStringList list = sequence.toString().split("+");
    char hotKey = 'E'; // По умолчанию будем возвращать 'E'

    foreach (QString str, list) {
        if(str != "Ctrl" && str != "Alt" && str != "Shift"){
            hotKey = str.at(0).unicode(); // Если не является модификатором, то возвращаем символ
        }
    }
    return hotKey;
}

// Обрабатываем событие нажатия последовательности горячих клавиш
bool MainWindow::nativeEvent(const QByteArray &eventType, void *message, long *result)
{
    Q_UNUSED(eventType)
    Q_UNUSED(result)
    MSG* msg = reinterpret_cast<MSG*>(message);

    if(msg->message == WM_HOTKEY){

        switch (msg->wParam) {
        case 100: {
            qDebug() << "Key Sequence worked";
            return true;
            break;
        }
        default:
            break;
        }
    }
    return false;
}
Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.
Поддержать автора Donate

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
Donate

Здравствуйте, уважаемые пользователи EVILEG !!!

Если сайт вам помог, то поддержите разработку сайта финансово, пожалуйста.

Вы можете сделать это следующими способами:

Спасибо, Евгений Легоцкой

О
18 ноября 2019 г. 15:54
Оксана

C++ - Тест 005. Структуры и Классы

  • Результат:66баллов,
  • Очки рейтинга-1
АГ
18 ноября 2019 г. 15:50
Антон Гурьев

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

  • Результат:46баллов,
  • Очки рейтинга-6
VZ
17 ноября 2019 г. 2:25
Vladimir Zhitkovsky

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

  • Результат:78баллов,
  • Очки рейтинга2
Последние комментарии
c
18 ноября 2019 г. 6:27
cyberaxe77

Моих знаний пока явно недостаточно, чтобы писать статьи. Так...небольшие заметки "на полях"))).
18 ноября 2019 г. 6:10
Евгений Легоцкой

Пока что на сайте нет активных пользователей PyQt5, кто бы мог писать статьи по PyQt5, к сожалению. Лично я только для статей пользуюсь этой библиотекой. Но можете стать одним из первых ;) Любой…
18 ноября 2019 г. 2:44
Евгений Легоцкой

Добрый день. На тот момент ничего не использовал дополнительно и никаких специальных настроек не делал. Просто собрал и получилось 10 мб.
c
17 ноября 2019 г. 14:25
cyberaxe77

Шикарно! Как обычно всё объясняется чётко, ясно и, по-возможности, кратко. Побольше бы контента по PyQt5...
ГВ
16 ноября 2019 г. 16:16
Гибралтар Вольфрамов

Разрешите узнать, как вы получили qt+qml приложение размером в 10мб(даже релизных). Дело в том, что пустое приложение, хоть и со стек вью, обходится мне на все 40мб пространства. Или же вы воспо…
Сейчас обсуждают на форуме
c
19 ноября 2019 г. 4:49
cyberaxe77

Я штудирую небезизвестную книгу Прохорёнка и Дронова. Будьте добры скинуть один-два примера с передачей ссылок в поток. Очень интересно. Заранее благодарю.
MP
19 ноября 2019 г. 4:13
Mikhail Petrov

Без разницы в дизайнере создается форма или не в дизайнере. Как вы добавляете в QTabWidget?
19 ноября 2019 г. 2:36
BlinCT

Всем привет. Если кто дебажил qml часть подскажиет пожалуйста, какие настрйоки требуются в Qt Creator? Я собирал 5.12.5 из исходников, в Настройкс в debugger у меня выставлен путь к со…
18 ноября 2019 г. 13:36
Intruder

Понятно. Я кстати так сейчас и сделал, добавил проект в проект и т.д. Спасибо!
EVILEG
О нас
Услуги
© EVILEG 2015-2019
Рекомендует хостинг TIMEWEB