275 lines
7.7 KiB
C++
275 lines
7.7 KiB
C++
|
#include "qhotkey.h"
|
|||
|
#include "qhotkey_p.h"
|
|||
|
#include <qt_windows.h>
|
|||
|
#include <QDebug>
|
|||
|
|
|||
|
#define HKEY_ID(nativeShortcut) (((nativeShortcut.key ^ (nativeShortcut.modifier << 8)) & 0x0FFF) | 0x7000)
|
|||
|
|
|||
|
class QHotkeyPrivateWin : public QHotkeyPrivate
|
|||
|
{
|
|||
|
public:
|
|||
|
// QAbstractNativeEventFilter interface
|
|||
|
bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE;
|
|||
|
|
|||
|
protected:
|
|||
|
// QHotkeyPrivate interface
|
|||
|
quint32 nativeKeycode(Qt::Key keycode, bool &ok) Q_DECL_OVERRIDE;
|
|||
|
quint32 nativeModifiers(Qt::KeyboardModifiers modifiers, bool &ok) Q_DECL_OVERRIDE;
|
|||
|
bool registerShortcut(QHotkey::NativeShortcut shortcut) Q_DECL_OVERRIDE;
|
|||
|
bool unregisterShortcut(QHotkey::NativeShortcut shortcut) Q_DECL_OVERRIDE;
|
|||
|
|
|||
|
private:
|
|||
|
static QString formatWinError(DWORD winError);
|
|||
|
};
|
|||
|
NATIVE_INSTANCE(QHotkeyPrivateWin)
|
|||
|
|
|||
|
bool QHotkeyPrivateWin::nativeEventFilter(const QByteArray &eventType, void *message, long *result)
|
|||
|
{
|
|||
|
Q_UNUSED(eventType);
|
|||
|
Q_UNUSED(result);
|
|||
|
|
|||
|
MSG *msg = static_cast<MSG *>(message);
|
|||
|
if (msg->message == WM_HOTKEY) {
|
|||
|
this->activateShortcut(QHotkey::NativeShortcut(HIWORD(msg->lParam), LOWORD(msg->lParam)));
|
|||
|
}
|
|||
|
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
quint32 QHotkeyPrivateWin::nativeKeycode(Qt::Key keycode, bool &ok)
|
|||
|
{
|
|||
|
ok = true;
|
|||
|
if (keycode <= 0xFFFF) { //Try to obtain the key from it's "character"
|
|||
|
const SHORT vKey = VkKeyScanW(keycode);
|
|||
|
if (vKey > -1) {
|
|||
|
return LOBYTE(vKey);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//find key from switch/case --> Only finds a very small subset of keys
|
|||
|
switch (keycode) {
|
|||
|
case Qt::Key_Escape:
|
|||
|
return VK_ESCAPE;
|
|||
|
case Qt::Key_Tab:
|
|||
|
case Qt::Key_Backtab:
|
|||
|
return VK_TAB;
|
|||
|
case Qt::Key_Backspace:
|
|||
|
return VK_BACK;
|
|||
|
case Qt::Key_Return:
|
|||
|
case Qt::Key_Enter:
|
|||
|
return VK_RETURN;
|
|||
|
case Qt::Key_Insert:
|
|||
|
return VK_INSERT;
|
|||
|
case Qt::Key_Delete:
|
|||
|
return VK_DELETE;
|
|||
|
case Qt::Key_Pause:
|
|||
|
return VK_PAUSE;
|
|||
|
case Qt::Key_Print:
|
|||
|
return VK_PRINT;
|
|||
|
case Qt::Key_Clear:
|
|||
|
return VK_CLEAR;
|
|||
|
case Qt::Key_Home:
|
|||
|
return VK_HOME;
|
|||
|
case Qt::Key_End:
|
|||
|
return VK_END;
|
|||
|
case Qt::Key_Left:
|
|||
|
return VK_LEFT;
|
|||
|
case Qt::Key_Up:
|
|||
|
return VK_UP;
|
|||
|
case Qt::Key_Right:
|
|||
|
return VK_RIGHT;
|
|||
|
case Qt::Key_Down:
|
|||
|
return VK_DOWN;
|
|||
|
case Qt::Key_PageUp:
|
|||
|
return VK_PRIOR;
|
|||
|
case Qt::Key_PageDown:
|
|||
|
return VK_NEXT;
|
|||
|
case Qt::Key_CapsLock:
|
|||
|
return VK_CAPITAL;
|
|||
|
case Qt::Key_NumLock:
|
|||
|
return VK_NUMLOCK;
|
|||
|
case Qt::Key_ScrollLock:
|
|||
|
return VK_SCROLL;
|
|||
|
|
|||
|
case Qt::Key_F1:
|
|||
|
return VK_F1;
|
|||
|
case Qt::Key_F2:
|
|||
|
return VK_F2;
|
|||
|
case Qt::Key_F3:
|
|||
|
return VK_F3;
|
|||
|
case Qt::Key_F4:
|
|||
|
return VK_F4;
|
|||
|
case Qt::Key_F5:
|
|||
|
return VK_F5;
|
|||
|
case Qt::Key_F6:
|
|||
|
return VK_F6;
|
|||
|
case Qt::Key_F7:
|
|||
|
return VK_F7;
|
|||
|
case Qt::Key_F8:
|
|||
|
return VK_F8;
|
|||
|
case Qt::Key_F9:
|
|||
|
return VK_F9;
|
|||
|
case Qt::Key_F10:
|
|||
|
return VK_F10;
|
|||
|
case Qt::Key_F11:
|
|||
|
return VK_F11;
|
|||
|
case Qt::Key_F12:
|
|||
|
return VK_F12;
|
|||
|
case Qt::Key_F13:
|
|||
|
return VK_F13;
|
|||
|
case Qt::Key_F14:
|
|||
|
return VK_F14;
|
|||
|
case Qt::Key_F15:
|
|||
|
return VK_F15;
|
|||
|
case Qt::Key_F16:
|
|||
|
return VK_F16;
|
|||
|
case Qt::Key_F17:
|
|||
|
return VK_F17;
|
|||
|
case Qt::Key_F18:
|
|||
|
return VK_F18;
|
|||
|
case Qt::Key_F19:
|
|||
|
return VK_F19;
|
|||
|
case Qt::Key_F20:
|
|||
|
return VK_F20;
|
|||
|
case Qt::Key_F21:
|
|||
|
return VK_F21;
|
|||
|
case Qt::Key_F22:
|
|||
|
return VK_F22;
|
|||
|
case Qt::Key_F23:
|
|||
|
return VK_F23;
|
|||
|
case Qt::Key_F24:
|
|||
|
return VK_F24;
|
|||
|
|
|||
|
case Qt::Key_Menu:
|
|||
|
return VK_APPS;
|
|||
|
case Qt::Key_Help:
|
|||
|
return VK_HELP;
|
|||
|
case Qt::Key_MediaNext:
|
|||
|
return VK_MEDIA_NEXT_TRACK;
|
|||
|
case Qt::Key_MediaPrevious:
|
|||
|
return VK_MEDIA_PREV_TRACK;
|
|||
|
case Qt::Key_MediaPlay:
|
|||
|
return VK_MEDIA_PLAY_PAUSE;
|
|||
|
case Qt::Key_MediaStop:
|
|||
|
return VK_MEDIA_STOP;
|
|||
|
case Qt::Key_VolumeDown:
|
|||
|
return VK_VOLUME_DOWN;
|
|||
|
case Qt::Key_VolumeUp:
|
|||
|
return VK_VOLUME_UP;
|
|||
|
case Qt::Key_VolumeMute:
|
|||
|
return VK_VOLUME_MUTE;
|
|||
|
case Qt::Key_Mode_switch:
|
|||
|
return VK_MODECHANGE;
|
|||
|
case Qt::Key_Select:
|
|||
|
return VK_SELECT;
|
|||
|
case Qt::Key_Printer:
|
|||
|
return VK_PRINT;
|
|||
|
case Qt::Key_Execute:
|
|||
|
return VK_EXECUTE;
|
|||
|
case Qt::Key_Sleep:
|
|||
|
return VK_SLEEP;
|
|||
|
case Qt::Key_Period:
|
|||
|
return VK_DECIMAL;
|
|||
|
case Qt::Key_Play:
|
|||
|
return VK_PLAY;
|
|||
|
case Qt::Key_Cancel:
|
|||
|
return VK_CANCEL;
|
|||
|
|
|||
|
case Qt::Key_Forward:
|
|||
|
return VK_BROWSER_FORWARD;
|
|||
|
case Qt::Key_Refresh:
|
|||
|
return VK_BROWSER_REFRESH;
|
|||
|
case Qt::Key_Stop:
|
|||
|
return VK_BROWSER_STOP;
|
|||
|
case Qt::Key_Search:
|
|||
|
return VK_BROWSER_SEARCH;
|
|||
|
case Qt::Key_Favorites:
|
|||
|
return VK_BROWSER_FAVORITES;
|
|||
|
case Qt::Key_HomePage:
|
|||
|
return VK_BROWSER_HOME;
|
|||
|
|
|||
|
case Qt::Key_LaunchMail:
|
|||
|
return VK_LAUNCH_MAIL;
|
|||
|
case Qt::Key_LaunchMedia:
|
|||
|
return VK_LAUNCH_MEDIA_SELECT;
|
|||
|
case Qt::Key_Launch0:
|
|||
|
return VK_LAUNCH_APP1;
|
|||
|
case Qt::Key_Launch1:
|
|||
|
return VK_LAUNCH_APP2;
|
|||
|
|
|||
|
case Qt::Key_Massyo:
|
|||
|
return VK_OEM_FJ_MASSHOU;
|
|||
|
case Qt::Key_Touroku:
|
|||
|
return VK_OEM_FJ_TOUROKU;
|
|||
|
|
|||
|
default:
|
|||
|
ok = false;
|
|||
|
return 0;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
quint32 QHotkeyPrivateWin::nativeModifiers(Qt::KeyboardModifiers modifiers, bool &ok)
|
|||
|
{
|
|||
|
quint32 nMods = 0;
|
|||
|
if (modifiers & Qt::ShiftModifier) {
|
|||
|
nMods |= MOD_SHIFT;
|
|||
|
}
|
|||
|
if (modifiers & Qt::ControlModifier) {
|
|||
|
nMods |= MOD_CONTROL;
|
|||
|
}
|
|||
|
if (modifiers & Qt::AltModifier) {
|
|||
|
nMods |= MOD_ALT;
|
|||
|
}
|
|||
|
if (modifiers & Qt::MetaModifier) {
|
|||
|
nMods |= MOD_WIN;
|
|||
|
}
|
|||
|
ok = true;
|
|||
|
return nMods;
|
|||
|
}
|
|||
|
|
|||
|
bool QHotkeyPrivateWin::registerShortcut(QHotkey::NativeShortcut shortcut)
|
|||
|
{
|
|||
|
BOOL ok = RegisterHotKey(NULL,
|
|||
|
HKEY_ID(shortcut),
|
|||
|
shortcut.modifier,
|
|||
|
shortcut.key);
|
|||
|
if (ok) {
|
|||
|
return true;
|
|||
|
} else {
|
|||
|
qDebug() << "Failed to register hotkey. Error:"
|
|||
|
<< qPrintable(QHotkeyPrivateWin::formatWinError(::GetLastError()));
|
|||
|
return false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
bool QHotkeyPrivateWin::unregisterShortcut(QHotkey::NativeShortcut shortcut)
|
|||
|
{
|
|||
|
BOOL ok = UnregisterHotKey(NULL, HKEY_ID(shortcut));
|
|||
|
if (ok) {
|
|||
|
return true;
|
|||
|
} else {
|
|||
|
qDebug() << "Failed to unregister hotkey. Error:"
|
|||
|
<< qPrintable(QHotkeyPrivateWin::formatWinError(::GetLastError()));
|
|||
|
return false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
QString QHotkeyPrivateWin::formatWinError(DWORD winError)
|
|||
|
{
|
|||
|
wchar_t *buffer = NULL;
|
|||
|
DWORD num = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
|
|||
|
NULL,
|
|||
|
winError,
|
|||
|
0,
|
|||
|
(LPWSTR)&buffer,
|
|||
|
0,
|
|||
|
NULL);
|
|||
|
if (buffer) {
|
|||
|
QString res = QString::fromWCharArray(buffer, num);
|
|||
|
LocalFree(buffer);
|
|||
|
return res;
|
|||
|
} else {
|
|||
|
return QString();
|
|||
|
}
|
|||
|
}
|