-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathkeylistener.cpp
More file actions
140 lines (119 loc) · 3.46 KB
/
keylistener.cpp
File metadata and controls
140 lines (119 loc) · 3.46 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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#include "KeyListener.h"
#include "logging.h"
using namespace std;
bool KeyListener::CheckHotKey(UINT iKey, UINT iModifiers)
{
bool aRes = RegisterHotKey(NULL, 0xFA, iModifiers , iKey);
if (aRes) UnregisterHotKey(NULL, 0xFA);
return aRes;
}
HANDLE KeyListener::newthread()
{
return CreateThread(NULL, 0, &Runnable::run_thread, this, 0, NULL);
}
void KeyListener::addKey(UINT iKey, KeyCallback_t iCallback)
// adding [alt+shift+iKey] combination
{
addKey(iKey, (MOD_ALT | MOD_SHIFT), iCallback );
}
void KeyListener::addKey(UINT iKey, UINT iModifiers, KeyCallback_t iCallback)
{
if (isRunning())
{
INFO("Cannot add new key when key listener is running!");
return;
}
if (_keyHandlers.insert(pair< pair<UINT, UINT>, KeyCallback_t>( {iKey, iModifiers&0xFF}, iCallback)).second == false)
{
INFO("The Key " << iKey << " is already added. You need to remove it first");
return;
}
}
void KeyListener::removeKey(UINT iKey)
{
removeKey(iKey, (MOD_ALT | MOD_SHIFT));
}
void KeyListener::removeKey(UINT iKey, UINT iModifiers)
{
if (isRunning())
{
INFO("Cannot remove key when key listener is running!");
return;
}
_keyHandlers.erase({iKey, iModifiers });
}
void KeyListener::clear()
{
_keyHandlers.clear();
}
void KeyListener::start()
{
if (_threadID == 0) //we can start only one thread per KeyListener ;)
{
_threadID = this->newthread();
if (!_threadID)
{
ERR("ERROR: cannot create thread: " << GetLastError());
}
}
else
{
INFO("Key Listener is already running!");
}
DBG("Key Listener started");
}
void KeyListener::stop()
{
if (_threadID != 0)
{
if (!TerminateThread(_threadID, 0))
{
ERR("ERROR: Cannot terminate KeiListener thread: " << GetLastError());
}
else
{
DBG("Key Listener stopped ");
UnregisterHotKey(NULL, 1);
_threadID = 0;
}
}
}
DWORD KeyListener::run()
{
BOOL res = true;
for (map<pair<UINT,UINT>, KeyCallback_t>::iterator aIter = _keyHandlers.begin(); aIter != _keyHandlers.end(); ++aIter)
{
res = RegisterHotKey(NULL, 1, aIter->first.second , aIter->first.first); // register hotkeys from the map
}
if (!res)
{
ERR("Error while trying to register keys");
return 1;
}
MSG msg = {0, 0, 0, 0, 0, 0, 0};
while ( (GetMessage(&msg, NULL, 0, 0) != 0) )
{
if (msg.message == WM_HOTKEY)
{
LPARAM ctrlKey = msg.lParam & 0xFFFF;
LPARAM key = (msg.lParam >> 16) & 0xFFFF;
DBG("ctrlKey: " << ctrlKey << " key: " << key);
//cout << "WM_HOTKEY received. key pressed: 0x" <<hex<<uppercase<<key << ", control key: 0x" << hex<<uppercase<<ctrlKey << endl;
try
{
_keyHandlers.at({key, ctrlKey})();
}
catch (const std::exception& e)
{
ERR("Unknown hotkeys received. Implementation error. Key: 0x" <<hex<<key << ", control key: 0x" << hex<<ctrlKey);
ERR("Exception details: " << e.what());
}
}
}
// in fact since we're killing this thread with TerminateThread()
// this line is never called
// but we also unregister hotkeys in KeyListener.stop() method so this line
// is just redundant.. but it's okay ;)
UnregisterHotKey(NULL, 1);
return 0;
}