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