source: trunk/src/comctl32/hotkey.cpp@ 2875

Last change on this file since 2875 was 2875, checked in by cbratschi, 26 years ago

C -> C++, WINE animate, treeview WM_VSCROLL fixed

File size: 15.5 KB
Line 
1/* $Id: hotkey.cpp,v 1.1 2000-02-23 17:09:42 cbratschi Exp $ */
2/*
3 * Hotkey control
4 *
5 * Copyright 1998, 1999 Eric Kohl
6 * Copyright 1999 Achim Hasenmueller
7 * Copyright 1999 Christoph Bratschi
8 *
9 * Status: Complete (perhaps some bugs)
10 * Version: 5.00
11 */
12
13#include "winbase.h"
14#include "commctrl.h"
15#include "hotkey.h"
16#include <string.h>
17
18#define HOTKEY_GetInfoPtr(hwnd) ((HOTKEY_INFO*)GetWindowLongA(hwnd,0))
19
20static VOID
21HOTKEY_Refresh(HWND hwnd,BOOL notify)
22{
23 InvalidateRect(hwnd,NULL,FALSE);
24
25 if (notify) SendMessageA(GetParent(hwnd),WM_COMMAND,MAKEWPARAM(GetWindowLongA(hwnd,GWL_ID),EN_CHANGE),hwnd);
26}
27
28static char*
29HOTKEY_ExtKey2Name(BYTE bVKHotKey)
30{
31 switch(bVKHotKey)
32 {
33 case VK_RETURN:
34 return "RETURN";
35
36 case VK_PRIOR:
37 return "PRIOR";
38
39 case VK_NEXT:
40 return "NEXT";
41
42 case VK_END:
43 return "END";
44
45 case VK_HOME:
46 return "HOME";
47
48 case VK_LEFT:
49 return "LEFT";
50
51 case VK_UP:
52 return "UP";
53
54 case VK_RIGHT:
55 return "RIGHT";
56
57 case VK_DOWN:
58 return "DOWN";
59
60 case VK_HELP:
61 return "HELP";
62
63 case VK_0:
64 return "0";
65
66 case VK_1:
67 return "1";
68
69 case VK_2:
70 return "2";
71
72 case VK_3:
73 return "3";
74
75 case VK_4:
76 return "4";
77
78 case VK_5:
79 return "5";
80
81 case VK_6:
82 return "6";
83
84 case VK_7:
85 return "7";
86
87 case VK_8:
88 return "8";
89
90 case VK_9:
91 return "9";
92
93 case VK_A:
94 return "A";
95
96 case VK_B:
97 return "B";
98
99 case VK_C:
100 return "C";
101
102 case VK_D:
103 return "D";
104
105 case VK_E:
106 return "E";
107
108 case VK_F:
109 return "F";
110
111 case VK_G:
112 return "G";
113
114 case VK_H:
115 return "H";
116
117 case VK_I:
118 return "I";
119
120 case VK_J:
121 return "J";
122
123 case VK_K:
124 return "K";
125
126 case VK_L:
127 return "L";
128
129 case VK_M:
130 return "M";
131
132 case VK_N:
133 return "N";
134
135 case VK_O:
136 return "O";
137
138 case VK_P:
139 return "P";
140
141 case VK_Q:
142 return "Q";
143
144 case VK_R:
145 return "R";
146
147 case VK_S:
148 return "S";
149
150 case VK_T:
151 return "T";
152
153 case VK_U:
154 return "U";
155
156 case VK_V:
157 return "V";
158
159 case VK_W:
160 return "W";
161
162 case VK_X:
163 return "Y";
164
165 case VK_Y:
166 return "X";
167
168 case VK_Z:
169 return "Z";
170
171 case VK_NUMPAD0:
172 return "NUMPAD0";
173
174 case VK_NUMPAD1:
175 return "NUMPAD1";
176
177 case VK_NUMPAD2:
178 return "NUMPAD2";
179
180 case VK_NUMPAD3:
181 return "NUMPAD3";
182
183 case VK_NUMPAD4:
184 return "NUMPAD4";
185
186 case VK_NUMPAD5:
187 return "NUMPAD5";
188
189 case VK_NUMPAD6:
190 return "NUMPAD6";
191
192 case VK_NUMPAD7:
193 return "NUMPAD7";
194
195 case VK_NUMPAD8:
196 return "NUMPAD8";
197
198 case VK_NUMPAD9:
199 return "NUMPAD9";
200
201 case VK_MULTIPLY:
202 return "MULTIPLY";
203
204 case VK_ADD:
205 return "ADD";
206
207 case VK_SEPARATOR:
208 return "SEPARATOR";
209
210 case VK_SUBTRACT:
211 return "SUBTRACT";
212
213 case VK_DECIMAL:
214 return "DECIMAL";
215
216 case VK_DIVIDE:
217 return "DIVIDE";
218
219 case VK_F1:
220 return "F1";
221
222 case VK_F2:
223 return "F2";
224
225 case VK_F3:
226 return "F3";
227
228 case VK_F4:
229 return "F4";
230
231 case VK_F5:
232 return "F5";
233
234 case VK_F6:
235 return "F6";
236
237 case VK_F7:
238 return "F7";
239
240 case VK_F8:
241 return "F8";
242
243 case VK_F9:
244 return "F9";
245
246 case VK_F10:
247 return "F10";
248
249 case VK_F11:
250 return "F11";
251
252 case VK_F12:
253 return "F12";
254
255 case VK_F13:
256 return "F13";
257
258 case VK_F14:
259 return "F14";
260
261 case VK_F15:
262 return "F15";
263
264 case VK_F16:
265 return "F16";
266
267 case VK_F17:
268 return "F17";
269
270 case VK_F18:
271 return "F18";
272
273 case VK_F19:
274 return "F19";
275
276 case VK_F20:
277 return "F20";
278
279 case VK_F21:
280 return "F21";
281
282 case VK_F22:
283 return "F22";
284
285 case VK_F23:
286 return "F23";
287
288 case VK_F24:
289 return "F24";
290
291 default:
292 return NULL;
293 }
294}
295
296static BYTE
297HOTKEY_Check(HOTKEY_INFO *infoPtr,BYTE bfMods)
298{
299 BYTE mods = bfMods & ~HOTKEYF_EXT;
300
301 if ((infoPtr->fwCombInv & HKCOMB_A && mods == HOTKEYF_ALT) ||
302 (infoPtr->fwCombInv & HKCOMB_C && mods == HOTKEYF_CONTROL) ||
303 (infoPtr->fwCombInv & HKCOMB_CA && mods == HOTKEYF_CONTROL | HOTKEYF_ALT) ||
304 (infoPtr->fwCombInv & HKCOMB_NONE && mods == 0) ||
305 (infoPtr->fwCombInv & HKCOMB_S && mods == HOTKEYF_SHIFT) ||
306 (infoPtr->fwCombInv & HKCOMB_SA && mods == HOTKEYF_SHIFT | HOTKEYF_ALT) ||
307 (infoPtr->fwCombInv & HKCOMB_SC && mods == HOTKEYF_SHIFT | HOTKEYF_CONTROL) ||
308 (infoPtr->fwCombInv & HKCOMB_SCA && mods == HOTKEYF_SHIFT | HOTKEYF_CONTROL | HOTKEYF_ALT))
309 return infoPtr->fwModInv | bfMods;
310 else
311 return bfMods;
312}
313
314
315static LRESULT
316HOTKEY_SetHotKey(HWND hwnd,WPARAM wParam,LPARAM lParam)
317{
318 HOTKEY_INFO *infoPtr = HOTKEY_GetInfoPtr(hwnd);
319
320 infoPtr->bVKHotKey = wParam & 0xFF;
321 infoPtr->bfMods = HOTKEY_Check(infoPtr,(wParam & 0xFF00)>>8);
322
323 HOTKEY_Refresh(hwnd,TRUE);
324
325 return 0;
326}
327
328
329static LRESULT
330HOTKEY_GetHotKey(HWND hwnd,WPARAM wParam,LPARAM lParam)
331{
332 HOTKEY_INFO *infoPtr = HOTKEY_GetInfoPtr(hwnd);
333
334 return MAKEWORD(infoPtr->bVKHotKey,infoPtr->bfMods);
335}
336
337
338static LRESULT
339HOTKEY_SetRules(HWND hwnd,WPARAM wParam,LPARAM lParam)
340{
341 HOTKEY_INFO *infoPtr = HOTKEY_GetInfoPtr(hwnd);
342 BYTE oldMods = infoPtr->bfMods;
343
344 infoPtr->fwCombInv = wParam;
345 infoPtr->fwModInv = lParam;
346
347 infoPtr->bfMods = HOTKEY_Check(infoPtr,infoPtr->bfMods);
348 if (infoPtr->bfMods != oldMods) HOTKEY_Refresh(hwnd,TRUE);
349
350 return 0;
351}
352
353
354static LRESULT
355HOTKEY_Char(HWND hwnd,WPARAM wParam,LPARAM lParam,BOOL sysKey)
356{
357 HOTKEY_INFO *infoPtr = HOTKEY_GetInfoPtr(hwnd);
358
359 if (wParam != infoPtr->bVKHotKey)
360 {
361 infoPtr->bVKHotKey = wParam & 0xFF;
362 infoPtr->bfMods &= ~HOTKEYF_EXT;
363 infoPtr->bfMods = HOTKEY_Check(infoPtr,infoPtr->bfMods);
364 HOTKEY_Refresh(hwnd,TRUE);
365 }
366 infoPtr->bfModsDown = 0;
367
368 return 0;
369}
370
371static LRESULT
372HOTKEY_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
373{
374 HOTKEY_INFO *infoPtr;
375 TEXTMETRICA tm;
376 HDC hdc;
377 RECT rect;
378
379 /* allocate memory for info structure */
380 infoPtr = (HOTKEY_INFO *)COMCTL32_Alloc (sizeof(HOTKEY_INFO));
381 SetWindowLongA(hwnd,0,(DWORD)infoPtr);
382
383 /* initialize info structure */
384
385 infoPtr->hFont = 0;
386 infoPtr->bFocus = FALSE;
387 infoPtr->bVKHotKey = 0;
388 infoPtr->bfMods = 0;
389 infoPtr->fwCombInv = 0;
390 infoPtr->fwModInv = 0;
391 infoPtr->bfModsDown = 0;
392
393 /* get default font height */
394 hdc = GetDC (hwnd);
395 GetTextMetricsA (hdc, &tm);
396 infoPtr->nHeight = tm.tmHeight;
397 ReleaseDC (hwnd, hdc);
398
399 GetClientRect(hwnd,&rect);
400 infoPtr->cursorPos.x = 0;
401 infoPtr->cursorPos.y = rect.bottom-tm.tmHeight;
402
403 return 0;
404}
405
406
407static LRESULT
408HOTKEY_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
409{
410 HOTKEY_INFO *infoPtr = HOTKEY_GetInfoPtr (hwnd);
411
412 /* free hotkey info data */
413 COMCTL32_Free (infoPtr);
414
415 return 0;
416}
417
418
419static LRESULT
420HOTKEY_EraseBackground (HWND hwnd, WPARAM wParam, LPARAM lParam)
421{
422 HBRUSH hBrush;
423 RECT rc;
424
425 hBrush = (HBRUSH)SendMessageA(GetParent(hwnd),WM_CTLCOLOREDIT,wParam,(LPARAM)hwnd);
426 if (!hBrush) hBrush = (HBRUSH)GetStockObject(WHITE_BRUSH);
427 GetClientRect(hwnd,&rc);
428 HideCaret(hwnd);
429 FillRect((HDC)wParam,&rc,hBrush);
430 ShowCaret(hwnd);
431
432 return -1;
433}
434
435
436static LRESULT
437HOTKEY_GetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
438{
439 HOTKEY_INFO *infoPtr = HOTKEY_GetInfoPtr (hwnd);
440
441 return infoPtr->hFont;
442}
443
444
445static LRESULT
446HOTKEY_KeyDown (HWND hwnd, WPARAM wParam, LPARAM lParam,BOOL sysKey)
447{
448 HOTKEY_INFO *infoPtr = HOTKEY_GetInfoPtr (hwnd);
449 INT newMods = (sysKey ? HOTKEYF_ALT:0) | infoPtr->bfModsDown;
450 INT newKey = (infoPtr->bfModsDown == 0) ? 0:infoPtr->bVKHotKey;
451
452 if (sysKey) infoPtr->bfModsDown |= HOTKEYF_ALT;
453 switch (wParam)
454 {
455 case VK_RETURN:
456 case VK_TAB:
457 case VK_SPACE:
458 case VK_DELETE:
459 case VK_ESCAPE:
460 case VK_BACK:
461 return DefWindowProcA (hwnd,sysKey ? WM_SYSKEYDOWN:WM_KEYDOWN, wParam, lParam);
462
463 case VK_SHIFT:
464 newMods |= HOTKEYF_SHIFT;
465 infoPtr->bfModsDown |= HOTKEYF_SHIFT;
466 break;
467
468 case VK_CONTROL:
469 newMods |= HOTKEYF_CONTROL;
470 infoPtr->bfModsDown |= HOTKEYF_CONTROL;
471 break;
472
473 default:
474 if (newKey != wParam && HOTKEY_ExtKey2Name(wParam))
475 {
476 infoPtr ->bVKHotKey = wParam & 0xFF;
477 newMods |= HOTKEYF_EXT;
478
479 infoPtr->bfMods = HOTKEY_Check(infoPtr,newMods);
480 HOTKEY_Refresh(hwnd,TRUE);
481 infoPtr->bfModsDown = 0;
482
483 return 0;
484 }
485 break;
486 }
487
488 newMods = HOTKEY_Check(infoPtr,newMods);
489 if (infoPtr->bfMods != newMods)
490 {
491 infoPtr->bVKHotKey = newKey;
492 infoPtr->bfMods = newMods;
493 HOTKEY_Refresh(hwnd,TRUE);
494 }
495
496 return 0;
497}
498
499
500static LRESULT
501HOTKEY_KeyUp (HWND hwnd, WPARAM wParam, LPARAM lParam,BOOL sysKey)
502{
503 HOTKEY_INFO *infoPtr = HOTKEY_GetInfoPtr(hwnd);
504 INT newMods = infoPtr->bfModsDown;
505
506 if (!infoPtr->bfModsDown) return 0;
507
508 if (sysKey)
509 {
510 newMods &= ~HOTKEYF_ALT;
511 infoPtr->bfModsDown &= ~HOTKEYF_ALT;
512 }
513 switch (wParam)
514 {
515 case VK_RETURN:
516 case VK_TAB:
517 case VK_SPACE:
518 case VK_DELETE:
519 case VK_ESCAPE:
520 case VK_BACK:
521 return DefWindowProcA (hwnd,sysKey ? WM_SYSKEYDOWN:WM_KEYDOWN, wParam, lParam);
522
523 case VK_SHIFT:
524 newMods &= ~HOTKEYF_SHIFT;
525 infoPtr->bfModsDown &= ~HOTKEYF_SHIFT;
526 break;
527
528 case VK_CONTROL:
529 newMods &= ~HOTKEYF_CONTROL;
530 infoPtr->bfModsDown &= ~HOTKEYF_CONTROL;
531 break;
532
533 default:
534 break;
535 }
536
537 newMods = HOTKEY_Check(infoPtr,newMods);
538 if (infoPtr->bfMods != newMods)
539 {
540 infoPtr->bfMods = newMods;
541 HOTKEY_Refresh(hwnd,TRUE);
542 }
543
544 return 0;
545}
546
547
548static LRESULT
549HOTKEY_KillFocus (HWND hwnd, WPARAM wParam, LPARAM lParam)
550{
551 HOTKEY_INFO *infoPtr = HOTKEY_GetInfoPtr (hwnd);
552
553 infoPtr->bfModsDown = 0;
554 infoPtr->bFocus = FALSE;
555 DestroyCaret();
556
557 return 0;
558}
559
560
561static LRESULT
562HOTKEY_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
563{
564 SetFocus (hwnd);
565
566 return 0;
567}
568
569
570static LRESULT
571HOTKEY_NCCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
572{
573 DWORD dwExStyle = GetWindowLongA (hwnd, GWL_EXSTYLE);
574 SetWindowLongA (hwnd, GWL_EXSTYLE, dwExStyle | WS_EX_CLIENTEDGE);
575 return DefWindowProcA (hwnd, WM_NCCREATE, wParam, lParam);
576}
577
578
579static VOID
580HOTKEY_Draw(HWND hwnd,HDC hdc)
581{
582 HOTKEY_INFO *infoPtr = HOTKEY_GetInfoPtr(hwnd);
583 RECT rect,newRect;
584 char text[50];
585 HFONT oldFont;
586
587 HideCaret(hwnd);
588 GetClientRect(hwnd,&rect);
589
590 //draw string
591 text[0] = 0;
592 if (infoPtr->bfMods & HOTKEYF_ALT) strcat(text,"ALT");
593 if (infoPtr->bfMods & HOTKEYF_CONTROL)
594 {
595 if (text[0]) strcat(text,"+");
596 strcat(text,"CONTROL");
597 }
598 if (infoPtr->bfMods & HOTKEYF_SHIFT)
599 {
600 if (text[0]) strcat(text,"+");
601 strcat(text,"SHIFT");
602 }
603
604 if (infoPtr->bVKHotKey)
605 {
606 if (infoPtr->bfMods & HOTKEYF_EXT)
607 {
608 char* name = HOTKEY_ExtKey2Name(infoPtr->bVKHotKey);
609
610 if (name)
611 {
612 if (text[0]) strcat(text,"+");
613 strcat(text,name);
614 }
615 } else
616 {
617 char char2[2];
618
619 if (text[0]) strcat(text,"+");
620 char2[0] = (char)infoPtr->bVKHotKey;
621 char2[1] = 0;
622 strcat(text,char2);
623 }
624 } else if (infoPtr->bfModsDown) strcat(text,"+");
625 if(infoPtr->hFont) oldFont = SelectObject(hdc,infoPtr->hFont);
626 SetBkMode(hdc,TRANSPARENT);
627 CopyRect(&newRect,&rect);
628 DrawTextA(hdc,text,strlen(text),&newRect,DT_LEFT | DT_BOTTOM | DT_SINGLELINE | DT_NOCLIP);
629 DrawTextA(hdc,text,strlen(text),&newRect,DT_LEFT | DT_BOTTOM | DT_SINGLELINE | DT_CALCRECT);
630 if (infoPtr->hFont) SelectObject(hdc,oldFont);
631 infoPtr->cursorPos.x = (newRect.right >= rect.right)? 0:newRect.right;
632 SetCaretPos(infoPtr->cursorPos.x,infoPtr->cursorPos.y);
633 ShowCaret(hwnd);
634}
635
636
637static LRESULT
638HOTKEY_Paint(HWND hwnd,WPARAM wParam,LPARAM lParam)
639{
640 PAINTSTRUCT ps;
641 HDC hdc;
642
643 if (wParam == 0) hdc = BeginPaint(hwnd,&ps);
644 else hdc = wParam;
645
646 HOTKEY_Draw(hwnd,hdc);
647
648 if (wParam == 0) EndPaint(hwnd,&ps);
649
650 return 0;
651}
652
653
654static LRESULT
655HOTKEY_SetFocus (HWND hwnd, WPARAM wParam, LPARAM lParam)
656{
657 HOTKEY_INFO *infoPtr = HOTKEY_GetInfoPtr (hwnd);
658
659 infoPtr->bFocus = TRUE;
660
661 CreateCaret(hwnd,(HBITMAP)0,1,infoPtr->nHeight);
662 SetCaretPos(infoPtr->cursorPos.x,infoPtr->cursorPos.y);
663 ShowCaret(hwnd);
664
665 return 0;
666}
667
668
669static LRESULT
670HOTKEY_SetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
671{
672 HOTKEY_INFO *infoPtr = HOTKEY_GetInfoPtr (hwnd);
673 TEXTMETRICA tm;
674 HDC hdc;
675 HFONT hOldFont = 0;
676
677 infoPtr->hFont = (HFONT)wParam;
678
679 hdc = GetDC (hwnd);
680 if (infoPtr->hFont)
681 hOldFont = SelectObject (hdc, infoPtr->hFont);
682
683 GetTextMetricsA (hdc, &tm);
684 infoPtr->nHeight = tm.tmHeight;
685
686 if (infoPtr->hFont)
687 SelectObject (hdc, hOldFont);
688 ReleaseDC (hwnd, hdc);
689
690 if (LOWORD(lParam)) HOTKEY_Refresh(hwnd,FALSE);
691
692 return 0;
693}
694
695
696static LRESULT WINAPI
697HOTKEY_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
698{
699 switch (uMsg)
700 {
701 case HKM_GETHOTKEY:
702 return HOTKEY_GetHotKey(hwnd,wParam,lParam);
703
704 case HKM_SETHOTKEY:
705 return HOTKEY_SetHotKey(hwnd,wParam,lParam);
706
707 case HKM_SETRULES:
708 return HOTKEY_SetRules(hwnd,wParam,lParam);
709
710 case WM_CHAR:
711 return HOTKEY_Char(hwnd,wParam,lParam,FALSE);
712
713 case WM_SYSCHAR:
714 return HOTKEY_Char(hwnd,wParam,lParam,TRUE);
715
716 case WM_CREATE:
717 return HOTKEY_Create (hwnd, wParam, lParam);
718
719 case WM_DESTROY:
720 return HOTKEY_Destroy (hwnd, wParam, lParam);
721
722 case WM_ERASEBKGND:
723 return HOTKEY_EraseBackground (hwnd, wParam, lParam);
724
725 case WM_GETDLGCODE:
726 return DLGC_WANTCHARS | DLGC_WANTARROWS;
727
728 case WM_GETFONT:
729 return HOTKEY_GetFont (hwnd, wParam, lParam);
730
731 case WM_KEYDOWN:
732 return HOTKEY_KeyDown(hwnd,wParam,lParam,FALSE);
733
734 case WM_SYSKEYDOWN:
735 return HOTKEY_KeyDown(hwnd,wParam,lParam,TRUE);
736
737 case WM_KEYUP:
738 return HOTKEY_KeyUp(hwnd,wParam,lParam,FALSE);
739
740 case WM_SYSKEYUP:
741 return HOTKEY_KeyUp(hwnd,wParam,lParam,TRUE);
742
743 case WM_KILLFOCUS:
744 return HOTKEY_KillFocus (hwnd, wParam, lParam);
745
746 case WM_LBUTTONDOWN:
747 return HOTKEY_LButtonDown (hwnd, wParam, lParam);
748
749 case WM_NCCREATE:
750 return HOTKEY_NCCreate (hwnd, wParam, lParam);
751
752 case WM_PAINT:
753 return HOTKEY_Paint(hwnd,wParam,lParam);
754
755 case WM_SETFOCUS:
756 return HOTKEY_SetFocus (hwnd, wParam, lParam);
757
758 case WM_SETFONT:
759 return HOTKEY_SetFont (hwnd, wParam, lParam);
760
761 default:
762// if (uMsg >= WM_USER)
763// ERR (hotkey, "unknown msg %04x wp=%08x lp=%08lx\n",
764// uMsg, wParam, lParam);
765 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
766 }
767 return 0;
768}
769
770
771VOID
772HOTKEY_Register (VOID)
773{
774 WNDCLASSA wndClass;
775
776//SvL: Don't check this now
777// if (GlobalFindAtomA (HOTKEY_CLASSA)) return;
778
779 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
780 wndClass.style = CS_GLOBALCLASS;
781 wndClass.lpfnWndProc = (WNDPROC)HOTKEY_WindowProc;
782 wndClass.cbClsExtra = 0;
783 wndClass.cbWndExtra = sizeof(HOTKEY_INFO *);
784 wndClass.hCursor = 0;
785 wndClass.hbrBackground = 0;
786 wndClass.lpszClassName = HOTKEY_CLASSA;
787
788 RegisterClassA (&wndClass);
789}
790
791
792VOID
793HOTKEY_Unregister (VOID)
794{
795 if (GlobalFindAtomA (HOTKEY_CLASSA))
796 UnregisterClassA (HOTKEY_CLASSA, (HINSTANCE)NULL);
797}
798
Note: See TracBrowser for help on using the repository browser.