ReactOS 0.4.17-dev-116-ga4b6fe9
hotkey.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Win32k subsystem
4 * PURPOSE: HotKey support
5 * FILE: win32ss/user/ntuser/hotkey.c
6 * PROGRAMER: Eric Kohl
7 */
8
9/*
10 * FIXME: Hotkey notifications are triggered by keyboard input (physical or programmatically)
11 * and since only desktops on WinSta0 can receive input in seems very wrong to allow
12 * windows/threads on destops not belonging to WinSta0 to set hotkeys (receive notifications).
13 * -- Gunnar
14 */
15
16#include <win32k.h>
18
19/* GLOBALS *******************************************************************/
20
21/*
22 * Hardcoded hotkeys. See http://ivanlef0u.fr/repo/windoz/VI20051005.html (DEAD_LINK)
23 * or https://web.archive.org/web/20170826161432/http://repo.meh.or.id/Windows/VI20051005.html .
24 *
25 * NOTE: The (Shift-)F12 keys are used only for the "UserDebuggerHotKey" setting
26 * which enables setting a key shortcut which, when pressed, establishes a
27 * breakpoint in the code being debugged:
28 * see https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc786263(v=ws.10)
29 * and https://flylib.com/books/en/4.441.1.33/1/ for more details.
30 * By default the key is VK-F12 on a 101-key keyboard, and is VK_SUBTRACT
31 * (hyphen / substract sign) on a 82-key keyboard.
32 */
33/* pti pwnd modifiers vk id next */
34// HOT_KEY hkF12 = {NULL, 1, 0, VK_F12, IDHK_F12, NULL};
35// HOT_KEY hkShiftF12 = {NULL, 1, MOD_SHIFT, VK_F12, IDHK_SHIFTF12, &hkF12};
36// HOT_KEY hkWinKey = {NULL, 1, MOD_WIN, 0, IDHK_WINKEY, &hkShiftF12};
37
40
41/* FUNCTIONS *****************************************************************/
42
43#define IsWindowHotKey(pHK) ( (pHK)->pti == NULL && (pHK)->id == IDHK_WNDKEY )
44
47{
48 UINT vk = VK_F12;
51
56
57 TRACE("Debugger hotkeys set up! If you see this you enabled Debug Prints. Congrats!\n");
58}
59
60/*
61 * IntGetModifiers
62 *
63 * Returns a value that indicates if the key is a modifier key, and
64 * which one.
65 */
66static
69{
70 UINT fModifiers = 0;
71
72 if (IS_KEY_DOWN(pKeyState, VK_SHIFT))
73 fModifiers |= MOD_SHIFT;
74
75 if (IS_KEY_DOWN(pKeyState, VK_CONTROL))
76 fModifiers |= MOD_CONTROL;
77
78 if (IS_KEY_DOWN(pKeyState, VK_MENU))
79 fModifiers |= MOD_ALT;
80
81 if (IS_KEY_DOWN(pKeyState, VK_LWIN) || IS_KEY_DOWN(pKeyState, VK_RWIN))
82 fModifiers |= MOD_WIN;
83
84 return fModifiers;
85}
86
87/*
88 * IntSwapModHKF
89 *
90 * Maps to/from MOD_/HOTKEYF_ (swaps the SHIFT and ALT bits)
91 */
92static inline
95{
96 return (Input & 2) | ((Input & 1) << 2) | ((Input >> 2) & 1);
97}
98
99/*
100 * UnregisterWindowHotKeys
101 *
102 * Removes hotkeys registered by specified window on its cleanup
103 */
106{
107 PHOT_KEY pHotKey = gphkFirst, phkNext, *pLink = &gphkFirst;
108
109 while (pHotKey)
110 {
111 /* Save next ptr for later use */
112 phkNext = pHotKey->pNext;
113
114 /* Should we delete this hotkey? */
115 if (pHotKey->pWnd == pWnd)
116 {
117 /* Update next ptr for previous hotkey and free memory */
118 *pLink = phkNext;
120 }
121 else /* This hotkey will stay, use its next ptr */
122 pLink = &pHotKey->pNext;
123
124 /* Move to the next entry */
125 pHotKey = phkNext;
126 }
127}
128
129/*
130 * UnregisterThreadHotKeys
131 *
132 * Removes hotkeys registered by specified thread on its cleanup
133 */
136{
137 PHOT_KEY pHotKey = gphkFirst, phkNext, *pLink = &gphkFirst;
138
139 while (pHotKey)
140 {
141 /* Save next ptr for later use */
142 phkNext = pHotKey->pNext;
143
144 /* Should we delete this hotkey? */
145 if (pHotKey->pti == pti)
146 {
147 /* Update next ptr for previous hotkey and free memory */
148 *pLink = phkNext;
150 }
151 else /* This hotkey will stay, use its next ptr */
152 pLink = &pHotKey->pNext;
153
154 /* Move to the next entry */
155 pHotKey = phkNext;
156 }
157}
158
159/*
160 * IsHotKey
161 *
162 * Checks if given key and modificators have corresponding hotkey
163 */
164static PHOT_KEY FASTCALL
165IsHotKey(UINT fsModifiers, WORD wVk)
166{
167 PHOT_KEY pHotKey = gphkFirst;
168
169 while (pHotKey)
170 {
171 if (pHotKey->fsModifiers == fsModifiers &&
172 pHotKey->vk == wVk)
173 {
174 /* We have found it */
175 return pHotKey;
176 }
177
178 /* Move to the next entry */
179 pHotKey = pHotKey->pNext;
180 }
181
182 return NULL;
183}
184
185/*
186 * co_UserProcessHotKeys
187 *
188 * Sends WM_HOTKEY message if given keys are hotkey
189 */
192{
193 UINT fModifiers;
194 PHOT_KEY pHotKey;
195 PWND pWnd;
196 BOOL DoNotPostMsg = FALSE;
197 BOOL IsModifier = FALSE;
198
199 if (wVk == VK_SHIFT || wVk == VK_CONTROL || wVk == VK_MENU ||
200 wVk == VK_LWIN || wVk == VK_RWIN)
201 {
202 /* Remember that this was a modifier */
203 IsModifier = TRUE;
204 }
205
206 fModifiers = IntGetModifiers(gafAsyncKeyState);
207
208 if (bIsDown)
209 {
210 if (IsModifier)
211 {
212 /* Modifier key down -- no hotkey trigger, but remember this */
213 gfsModOnlyCandidate = fModifiers;
214 return FALSE;
215 }
216 else
217 {
218 /* Regular key down -- check for hotkey, and reset mod candidates */
219 pHotKey = IsHotKey(fModifiers, wVk);
221 }
222 }
223 else
224 {
225 if (IsModifier)
226 {
227 /* Modifier key up -- modifier-only keys are triggered here */
228 pHotKey = IsHotKey(gfsModOnlyCandidate, 0);
230 }
231 else
232 {
233 /* Regular key up -- no hotkey, but reset mod-only candidates */
235 return FALSE;
236 }
237 }
238
239 if (pHotKey)
240 {
241 TRACE("Hot key pressed (pWnd %p, id %d)\n", pHotKey->pWnd, pHotKey->id);
242
243 /* FIXME: See comment about "UserDebuggerHotKey" on top of this file. */
244 if (pHotKey->id == IDHK_SHIFTF12 || pHotKey->id == IDHK_F12)
245 {
246 if (bIsDown)
247 {
248 ERR("Hot key pressed for Debug Activation! ShiftF12 = %d or F12 = %d\n",pHotKey->id == IDHK_SHIFTF12 , pHotKey->id == IDHK_F12);
249 //DoNotPostMsg = co_ActivateDebugger(); // FIXME
250 }
251 return DoNotPostMsg;
252 }
253
254 /* WIN and F12 keys are not hardcoded here. See comments on top of this file. */
255 if (pHotKey->id == IDHK_WINKEY)
256 {
257 ASSERT(!bIsDown);
259 if (pWnd)
260 {
261 TRACE("System Hot key Id %d Key %u\n", pHotKey->id, wVk );
263 co_IntShellHookNotify(HSHELL_TASKMAN, 0, 0);
264 return FALSE;
265 }
266 }
267
268 if (pHotKey->id == IDHK_SNAP_LEFT ||
269 pHotKey->id == IDHK_SNAP_RIGHT ||
270 pHotKey->id == IDHK_SNAP_UP ||
271 pHotKey->id == IDHK_SNAP_DOWN)
272 {
273 HWND topWnd = UserGetForegroundWindow();
274 if (topWnd)
275 {
276 UserPostMessage(topWnd, WM_KEYDOWN, wVk, 0);
277 }
278 return TRUE;
279 }
280
281 if (!pHotKey->pWnd)
282 {
283 TRACE("UPTM Hot key Id %d Key %u\n", pHotKey->id, wVk );
284 UserPostThreadMessage(pHotKey->pti, WM_HOTKEY, pHotKey->id, MAKELONG(fModifiers, wVk));
285 //ptiLastInput = pHotKey->pti;
286 return TRUE; /* Don't send any message */
287 }
288 else
289 {
290 pWnd = pHotKey->pWnd;
291 if (pWnd == PWND_BOTTOM)
292 {
293 if (gpqForeground == NULL)
294 return FALSE;
295
297 }
298
299 if (pWnd)
300 {
301 // pWnd->head.rpdesk->pDeskInfo->spwndShell needs testing.
303 {
305 co_IntShellHookNotify(HSHELL_TASKMAN, 0, 0);
306 }
307 else if (IsWindowHotKey(pHotKey))
308 {
309 /* WM_SETHOTKEY notifies with WM_SYSCOMMAND, not WM_HOTKEY */
310 if (bIsDown)
311 {
316 }
317 }
318 else
319 {
320 TRACE("UPM Hot key Id %d Key %u\n", pHotKey->id, wVk );
321 UserPostMessage(UserHMGetHandle(pWnd), WM_HOTKEY, pHotKey->id, MAKELONG(fModifiers, wVk));
322 }
323 //ptiLastInput = pWnd->head.pti;
324 return TRUE; /* Don't send any message */
325 }
326 }
327 }
328 return FALSE;
329}
330
331
332/*
333 * DefWndGetHotKey --- GetHotKey message support
334 */
337{
338 PHOT_KEY pHotKey = gphkFirst;
339
340 WARN("DefWndGetHotKey\n");
341
342 while (pHotKey)
343 {
344 if (pHotKey->pWnd == pWnd && IsWindowHotKey(pHotKey))
345 {
346 /* We have found it */
347 return MAKEWORD(pHotKey->vk, IntSwapModHKF(pHotKey->fsModifiers));
348 }
349
350 /* Move to the next entry */
351 pHotKey = pHotKey->pNext;
352 }
353
354 return 0;
355}
356
357/*
358 * DefWndSetHotKey --- SetHotKey message support
359 */
362{
363 const UINT fsModifiers = IntSwapModHKF(HIBYTE(wParam));
364 const UINT vk = LOBYTE(wParam);
365 PHOT_KEY pHotKey, *pLink;
366 INT iRet = 1;
367
368 WARN("DefWndSetHotKey wParam 0x%x\n", wParam);
369
370 // A hot key cannot be associated with a child window.
371 if (pWnd->style & WS_CHILD)
372 return 0;
373
374 // VK_ESCAPE, VK_SPACE, VK_TAB and VK_PACKET are invalid hot keys.
375 if (vk == VK_ESCAPE || vk == VK_SPACE || vk == VK_TAB || vk == VK_PACKET)
376 {
377 return -1;
378 }
379
380 if (wParam)
381 {
382 pHotKey = gphkFirst;
383 while (pHotKey)
384 {
385 if (pHotKey->fsModifiers == fsModifiers &&
386 pHotKey->vk == vk &&
387 IsWindowHotKey(pHotKey))
388 {
389 if (pHotKey->pWnd != pWnd)
390 iRet = 2; // Another window already has the same hot key.
391 break;
392 }
393
394 /* Move to the next entry */
395 pHotKey = pHotKey->pNext;
396 }
397 }
398
399 pHotKey = gphkFirst;
400 pLink = &gphkFirst;
401 while (pHotKey)
402 {
403 if (pHotKey->pWnd == pWnd && IsWindowHotKey(pHotKey))
404 {
405 /* This window has already hotkey registered */
406 break;
407 }
408
409 /* Move to the next entry */
410 pLink = &pHotKey->pNext;
411 pHotKey = pHotKey->pNext;
412 }
413
414 if (wParam)
415 {
416 if (!pHotKey)
417 {
418 /* Create new hotkey */
420 if (pHotKey == NULL)
421 return 0;
422
423 pHotKey->pWnd = pWnd;
424 pHotKey->id = IDHK_WNDKEY; // Don't care, these hot keys are unrelated to the hot keys set by RegisterHotKey
425 pHotKey->pNext = gphkFirst;
426 gphkFirst = pHotKey;
427 }
428
429 /* A window can only have one hot key. If the window already has a
430 hot key associated with it, the new hot key replaces the old one. */
431 pHotKey->pti = NULL; /* IsWindowHotKey */
432 pHotKey->fsModifiers = fsModifiers;
433 pHotKey->vk = vk;
434 }
435 else if (pHotKey)
436 {
437 /* Remove hotkey */
438 *pLink = pHotKey->pNext;
440 }
441
442 return iRet;
443}
444
445
448 int id,
449 UINT fsModifiers,
450 UINT vk)
451{
452 PHOT_KEY pHotKey;
453 PTHREADINFO pHotKeyThread;
454
455 /* Find the hotkey thread */
456 if (pWnd == NULL || pWnd == PWND_BOTTOM)
457 {
458 pHotKeyThread = PsGetCurrentThreadWin32Thread(); // gptiCurrent;
459 }
460 else
461 {
462 pHotKeyThread = pWnd->head.pti;
463 }
464
465 /* Ignore the VK_PACKET key since it is not a real keyboard input */
466 if (vk == VK_PACKET)
467 return FALSE;
468
469 /* Check whether we modify an existing hotkey */
470 if (IsHotKey(fsModifiers, vk))
471 {
473 WARN("Hotkey already exists\n");
474 return FALSE;
475 }
476
477 /* Create a new hotkey */
479 if (pHotKey == NULL)
480 {
482 return FALSE;
483 }
484
485 pHotKey->pti = pHotKeyThread;
486 pHotKey->pWnd = pWnd;
487 pHotKey->fsModifiers = fsModifiers;
488 pHotKey->vk = vk;
489 pHotKey->id = id;
490
491 /* Insert the hotkey into the global list */
492 pHotKey->pNext = gphkFirst;
493 gphkFirst = pHotKey;
494
495 return TRUE;
496}
497
500{
501 PHOT_KEY pHotKey = gphkFirst, phkNext, *pLink = &gphkFirst;
502 BOOL bRet = FALSE;
503
504 while (pHotKey)
505 {
506 /* Save next ptr for later use */
507 phkNext = pHotKey->pNext;
508
509 /* Should we delete this hotkey? */
510 if (pHotKey->pWnd == pWnd && pHotKey->id == id)
511 {
512 /* Update next ptr for previous hotkey and free memory */
513 *pLink = phkNext;
515
516 bRet = TRUE;
517 }
518 else
519 {
520 /* This hotkey will stay, use its next ptr */
521 pLink = &pHotKey->pNext;
522 }
523
524 /* Move to the next entry */
525 pHotKey = phkNext;
526 }
527
528 return bRet;
529}
530
531
532/* SYSCALLS *****************************************************************/
533
536 int id,
537 UINT fsModifiers,
538 UINT vk)
539{
540 PWND pWnd = NULL;
541 BOOL bRet = FALSE;
542
543 TRACE("Enter NtUserRegisterHotKey\n");
544
545 // FIXME: Does Win2k3 support MOD_NOREPEAT?
546 if (fsModifiers & ~(MOD_ALT | MOD_CONTROL | MOD_SHIFT | MOD_WIN))
547 {
548 WARN("Invalid modifiers: %x\n", fsModifiers);
550 return FALSE;
551 }
552
554
555 /* Check the hotkey thread */
556 if (hWnd == NULL)
557 {
558 pWnd = NULL;
559 }
560 else
561 {
563 if (!pWnd)
564 goto cleanup;
565
566 /* FIXME?? "Fix" wine msg "Window on another thread" test_hotkey */
567 if (pWnd->head.pti != gptiCurrent)
568 {
570 WARN("Must be from the same Thread.\n");
571 goto cleanup;
572 }
573 }
574
575 bRet = UserRegisterHotKey(pWnd, id, fsModifiers, vk);
576
577cleanup:
578 TRACE("Leave NtUserRegisterHotKey, ret=%i\n", bRet);
579 UserLeave();
580 return bRet;
581}
582
585{
586 BOOL bRet = FALSE;
587 PWND pWnd = NULL;
588
589 TRACE("Enter NtUserUnregisterHotKey\n");
591
592 /* Fail if the given window is invalid */
593 if (hWnd && !(pWnd = UserGetWindowObject(hWnd)))
594 goto cleanup;
595
596 bRet = UserUnregisterHotKey(pWnd, id);
597
598cleanup:
599 TRACE("Leave NtUserUnregisterHotKey, ret=%i\n", bRet);
600 UserLeave();
601 return bRet;
602}
603
604/* EOF */
HWND hWnd
Definition: settings.c:17
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
#define DBG_DEFAULT_CHANNEL(ch)
Definition: debug.h:106
WPARAM wParam
Definition: combotst.c:138
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define APIENTRY
Definition: api.h:79
static void cleanup(void)
Definition: main.c:1335
unsigned short vk
Definition: console.c:118
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define PagedPool
Definition: env_spec_w32.h:308
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned int BOOL
Definition: ntddk_ex.h:94
PUSER_MESSAGE_QUEUE gpqForeground
Definition: focus.c:13
HWND FASTCALL UserGetForegroundWindow(VOID)
Definition: focus.c:1418
GLuint id
Definition: glext.h:5910
#define IDHK_SNAP_LEFT
Definition: hotkey.h:20
#define IDHK_WNDKEY
Definition: hotkey.h:17
#define IDHK_WINKEY
Definition: hotkey.h:16
#define IDHK_SNAP_UP
Definition: hotkey.h:22
#define IDHK_F12
Definition: hotkey.h:14
#define IDHK_SNAP_DOWN
Definition: hotkey.h:23
#define IDHK_SNAP_RIGHT
Definition: hotkey.h:21
#define IDHK_SHIFTF12
Definition: hotkey.h:15
#define MOD_ALT
Definition: imm.h:184
#define MOD_SHIFT
Definition: imm.h:186
#define MOD_CONTROL
Definition: imm.h:185
#define UserHMGetHandle(obj)
Definition: ntuser.h:230
#define PWND_BOTTOM
Definition: ntuser.h:769
#define LOBYTE(W)
Definition: jmemdos.c:487
#define HIBYTE(W)
Definition: jmemdos.c:486
LONG_PTR LPARAM
Definition: minwindef.h:175
UINT_PTR WPARAM
Definition: minwindef.h:174
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
unsigned int UINT
Definition: ndis.h:50
#define FASTCALL
Definition: nt_native.h:50
#define ENHANCED_KEYBOARD(Id)
Definition: ntddkbd.h:105
PVOID NTAPI PsGetCurrentThreadWin32Thread(VOID)
Definition: thread.c:805
PWINSTATION_OBJECT InputWindowStation
Definition: winsta.c:21
VOID FASTCALL UserLeave(VOID)
Definition: ntuser.c:255
PTHREADINFO gptiCurrent
Definition: ntuser.c:15
VOID FASTCALL UserEnterExclusive(VOID)
Definition: ntuser.c:247
#define WS_CHILD
Definition: pedump.c:617
BYTE * PBYTE
Definition: pedump.c:66
@ Input
Definition: arc.h:93
#define TRACE(s)
Definition: solgame.cpp:4
Definition: hotkey.h:4
UINT fsModifiers
Definition: hotkey.h:7
PTHREADINFO pti
Definition: hotkey.h:5
struct _HOT_KEY * pNext
Definition: hotkey.h:10
INT id
Definition: hotkey.h:9
UINT vk
Definition: hotkey.h:8
PWND pWnd
Definition: hotkey.h:6
KEYBOARD_ID KeyboardIdentifier
Definition: ntddkbd.h:124
HANDLE ShellWindow
Definition: winsta.h:43
Definition: ntuser.h:694
THRDESKHEAD head
Definition: ntuser.h:695
DWORD style
Definition: ntuser.h:706
unsigned char UCHAR
Definition: typedefs.h:53
#define MAKEWORD(a, b)
Definition: typedefs.h:248
#define NTAPI
Definition: typedefs.h:36
int32_t INT
Definition: typedefs.h:58
#define MAKELONG(a, b)
Definition: typedefs.h:249
PWND FASTCALL UserGetWindowObject(HWND hWnd)
Definition: window.c:123
#define ValidateHwndNoErr(hwnd)
Definition: precomp.h:97
VOID co_IntShellHookNotify(WPARAM Message, WPARAM wParam, LPARAM lParam)
Definition: desktop.c:1704
BOOL APIENTRY NtUserUnregisterHotKey(HWND hWnd, int id)
Definition: hotkey.c:584
BOOL FASTCALL UserRegisterHotKey(PWND pWnd, int id, UINT fsModifiers, UINT vk)
Definition: hotkey.c:447
static PHOT_KEY FASTCALL IsHotKey(UINT fsModifiers, WORD wVk)
Definition: hotkey.c:165
BOOL NTAPI co_UserProcessHotKeys(WORD wVk, BOOL bIsDown)
Definition: hotkey.c:191
BOOL APIENTRY NtUserRegisterHotKey(HWND hWnd, int id, UINT fsModifiers, UINT vk)
Definition: hotkey.c:535
UINT FASTCALL DefWndGetHotKey(PWND pWnd)
Definition: hotkey.c:336
PHOT_KEY gphkFirst
Definition: hotkey.c:38
VOID FASTCALL UnregisterThreadHotKeys(PTHREADINFO pti)
Definition: hotkey.c:135
VOID FASTCALL SetDebugHotKeys(VOID)
Definition: hotkey.c:46
UINT gfsModOnlyCandidate
Definition: hotkey.c:39
static UCHAR IntSwapModHKF(UINT Input)
Definition: hotkey.c:94
#define IsWindowHotKey(pHK)
Definition: hotkey.c:43
static UINT FASTCALL IntGetModifiers(PBYTE pKeyState)
Definition: hotkey.c:68
VOID FASTCALL UnregisterWindowHotKeys(PWND pWnd)
Definition: hotkey.c:105
INT FASTCALL DefWndSetHotKey(PWND pWnd, WPARAM wParam)
Definition: hotkey.c:361
BOOL FASTCALL UserUnregisterHotKey(PWND pWnd, int id)
Definition: hotkey.c:499
KEYBOARD_ATTRIBUTES gKeyboardInfo
Definition: keyboard.c:17
BYTE gafAsyncKeyState[256 *2/8]
Definition: keyboard.c:13
#define IS_KEY_DOWN(ks, vk)
Definition: input.h:102
BOOL FASTCALL UserPostMessage(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam)
Definition: message.c:1395
BOOL FASTCALL UserPostThreadMessage(PTHREADINFO pti, UINT Msg, WPARAM wParam, LPARAM lParam)
Definition: message.c:1358
#define USERTAG_HOTKEY
Definition: tags.h:238
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:21
#define ERROR_WINDOW_OF_OTHER_THREAD
Definition: winerror.h:1234
#define ERROR_HOTKEY_ALREADY_REGISTERED
Definition: winerror.h:1235
#define ERROR_INVALID_FLAGS
Definition: winerror.h:907
#define WM_SYSCOMMAND
Definition: winuser.h:1769
#define VK_F12
Definition: winuser.h:2302
#define VK_TAB
Definition: winuser.h:2235
#define MOD_WIN
Definition: winuser.h:2686
#define VK_SPACE
Definition: winuser.h:2255
#define VK_CONTROL
Definition: winuser.h:2239
#define SC_TASKLIST
Definition: winuser.h:2635
#define SC_HOTKEY
Definition: winuser.h:2637
#define VK_LWIN
Definition: winuser.h:2271
#define WM_HOTKEY
Definition: winuser.h:1907
#define VK_SHIFT
Definition: winuser.h:2238
#define WM_KEYDOWN
Definition: winuser.h:1743
#define VK_ESCAPE
Definition: winuser.h:2250
#define VK_RWIN
Definition: winuser.h:2272
#define VK_SUBTRACT
Definition: winuser.h:2288
#define VK_MENU
Definition: winuser.h:2240