123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313 |
- #include "qhotkey.h"
- #include "qhotkey_p.h"
- #include <QDebug>
- #include <QTimer>
- #include <qt_windows.h>
- #define HKEY_ID(nativeShortcut) \
- (((nativeShortcut.key ^ (nativeShortcut.modifier << 8)) & 0x0FFF) | 0x7000)
- #if !defined(MOD_NOREPEAT)
- #define MOD_NOREPEAT 0x4000
- #endif
- class QHotkeyPrivateWin : public QHotkeyPrivate
- {
- public:
- QHotkeyPrivateWin();
- // QAbstractNativeEventFilter interface
- bool nativeEventFilter(const QByteArray& eventType,
- void* message,
- long* result) Q_DECL_OVERRIDE;
- protected:
- void pollForHotkeyRelease();
- // 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);
- QTimer pollTimer;
- QHotkey::NativeShortcut polledShortcut;
- };
- NATIVE_INSTANCE(QHotkeyPrivateWin)
- QHotkeyPrivateWin::QHotkeyPrivateWin()
- {
- pollTimer.setInterval(50);
- connect(&pollTimer,
- &QTimer::timeout,
- this,
- &QHotkeyPrivateWin::pollForHotkeyRelease);
- }
- bool QHotkeyPrivate::isPlatformSupported()
- {
- return true;
- }
- 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) {
- QHotkey::NativeShortcut shortcut = { HIWORD(msg->lParam),
- LOWORD(msg->lParam) };
- this->activateShortcut(shortcut);
- this->polledShortcut = shortcut;
- this->pollTimer.start();
- }
- return false;
- }
- void QHotkeyPrivateWin::pollForHotkeyRelease()
- {
- bool pressed =
- (GetAsyncKeyState(this->polledShortcut.key) & (1 << 15)) != 0;
- if (!pressed) {
- this->pollTimer.stop();
- this->releaseShortcut(this->polledShortcut);
- }
- }
- 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(static_cast<WCHAR>(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:
- if (keycode <= 0xFFFF)
- return (byte)keycode;
- else {
- 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 + MOD_NOREPEAT, shortcut.key);
- if (ok)
- return true;
- else {
- error = QHotkeyPrivateWin::formatWinError(::GetLastError());
- return false;
- }
- }
- bool QHotkeyPrivateWin::unregisterShortcut(QHotkey::NativeShortcut shortcut)
- {
- BOOL ok = UnregisterHotKey(NULL, HKEY_ID(shortcut));
- if (ok)
- return true;
- else {
- error = 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();
- }
|