-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathHotkeyManager.cpp
More file actions
94 lines (80 loc) · 2.98 KB
/
HotkeyManager.cpp
File metadata and controls
94 lines (80 loc) · 2.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include "pch.h"
#include "HotkeyManager.h"
using namespace interop;
HotkeyManager::HotkeyManager()
{
keyboardEventCallback = gcnew KeyboardEventCallback(this, &HotkeyManager::KeyboardEventProc);
isActiveCallback = gcnew IsActiveCallback(this, &HotkeyManager::IsActiveProc);
filterKeyboardCallback = gcnew FilterKeyboardEvent(this, &HotkeyManager::FilterKeyboardProc);
keyboardHook = gcnew KeyboardHook(
keyboardEventCallback,
isActiveCallback,
filterKeyboardCallback);
hotkeys = gcnew Dictionary<HOTKEY_HANDLE, HotkeyCallback ^>();
pressedKeys = gcnew Hotkey();
keyboardHook->Start();
}
HotkeyManager::~HotkeyManager()
{
delete keyboardHook;
}
// When all Shortcut keys are pressed, fire the HotkeyCallback event.
void HotkeyManager::KeyboardEventProc(KeyboardEvent ^ ev)
{
// pressedKeys always stores the latest keyboard state
auto pressedKeysHandle = GetHotkeyHandle(pressedKeys);
if (hotkeys->ContainsKey(pressedKeysHandle))
{
hotkeys[pressedKeysHandle]->Invoke();
// After invoking the hotkey send a dummy key to prevent Start Menu from activating
INPUT dummyEvent[1] = {};
dummyEvent[0].type = INPUT_KEYBOARD;
dummyEvent[0].ki.wVk = 0xFF;
dummyEvent[0].ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, dummyEvent, sizeof(INPUT));
}
}
// Hotkeys are intended to be global, therefore they are always active no matter the
// context in which the keypress occurs.
bool HotkeyManager::IsActiveProc()
{
return true;
}
// KeyboardEvent callback is only fired for relevant key events.
bool HotkeyManager::FilterKeyboardProc(KeyboardEvent ^ ev)
{
// Updating the pressed keys here so we know if the keypress event should be propagated or not.
pressedKeys->Win = (GetAsyncKeyState(VK_LWIN) & 0x8000) || (GetAsyncKeyState(VK_RWIN) & 0x8000);
pressedKeys->Ctrl = GetAsyncKeyState(VK_CONTROL) & 0x8000;
pressedKeys->Alt = GetAsyncKeyState(VK_MENU) & 0x8000;
pressedKeys->Shift = GetAsyncKeyState(VK_SHIFT) & 0x8000;
pressedKeys->Key = ev->key;
// Convert to hotkey handle
auto pressedKeysHandle = GetHotkeyHandle(pressedKeys);
// Check if any hotkey matches the pressed keys if the current key event is a key down event
if ((ev->message == WM_KEYDOWN || ev->message == WM_SYSKEYDOWN) && hotkeys->ContainsKey(pressedKeysHandle))
{
return true;
}
return false;
}
// NOTE: Replaces old hotkey if one already present.
HOTKEY_HANDLE HotkeyManager::RegisterHotkey(Hotkey ^ hotkey, HotkeyCallback ^ callback)
{
auto handle = GetHotkeyHandle(hotkey);
hotkeys[handle] = callback;
return handle;
}
void HotkeyManager::UnregisterHotkey(HOTKEY_HANDLE handle)
{
hotkeys->Remove(handle);
}
HOTKEY_HANDLE HotkeyManager::GetHotkeyHandle(Hotkey ^ hotkey)
{
HOTKEY_HANDLE handle = hotkey->Key;
handle |= hotkey->Win << 8;
handle |= hotkey->Ctrl << 9;
handle |= hotkey->Shift << 10;
handle |= hotkey->Alt << 11;
return handle;
}