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; }