Evgenii Legotckoi
Evgenii Legotckoi8 января 2016 г. 22:53

Qt WinAPI - Урок 006. Разбор QKeySequence для 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 хостинг.

Вам это нравится? Поделитесь в социальных сетях!

Комментарии

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

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

  • Результат:85баллов,
  • Очки рейтинга6
в

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

  • Результат:50баллов,
  • Очки рейтинга-4
l

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

  • Результат:91баллов,
  • Очки рейтинга8
Последние комментарии
k
kmssr9 февраля 2024 г. 5:43
Qt Linux - Урок 001. Автозапуск Qt приложения под Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
АК
Анатолий Кононенко5 февраля 2024 г. 12:50
Qt WinAPI - Урок 007. Работаем с ICMP Ping в Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
EVA
EVA25 декабря 2023 г. 21:30
Boost - статическая линковка в CMake проекте под Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
J
JonnyJo25 декабря 2023 г. 19:38
Boost - статическая линковка в CMake проекте под Windows Сделал всё по-как у вас, но выдаёт ошибку [build] LINK : fatal error LNK1104: не удается открыть файл "libboost_locale-vc142-mt-gd-x64-1_74.lib" Хоть убей, не могу понять в чём дел…
G
Gvozdik19 декабря 2023 г. 8:01
Qt/C++ - Урок 056. Подключение библиотеки Boost в Qt для компиляторов MinGW и MSVC Для решения твой проблемы добавь в файл .pro строчку "LIBS += -lws2_32" она решит проблему , лично мне помогло.
Сейчас обсуждают на форуме
P
Pisych27 февраля 2023 г. 15:04
Как получить в массив значения из связанной модели? Спасибо, разобрался:))
AC
Alexandru Codreanu19 января 2024 г. 22:57
QML Обнулить значения SpinBox Доброго времени суток, не могу разобраться с обнулением значение SpinBox находящего в делегате. import QtQuickimport QtQuick.ControlsWindow { width: 640 height: 480 visible: tr…
BlinCT
BlinCT27 декабря 2023 г. 19:57
Растягивать Image на парент по высоте Ну и само собою дял включения scrollbar надо чтобы был Flickable. Так что выходит как то так Flickable{ id: root anchors.fill: parent clip: true property url linkFile p…
Дмитрий
Дмитрий10 января 2024 г. 15:18
Qt Creator загружает всю оперативную память Проблема решена. Удалось разобраться с помощью утилиты strace. Запустил ее: strace ./qtcreator Начал выводиться весь лог работы креатора. В один момент он начал считывать фай…
Evgenii Legotckoi
Evgenii Legotckoi12 декабря 2023 г. 17:48
Побуквенное сравнение двух строк Добрый день. Там случайно не высылается этот сигнал textChanged ещё и при форматировани текста? Если решиать в лоб, то можно просто отключать сигнал/слотовое соединение внутри слота и …

Следите за нами в социальных сетях