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

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

unicode and other changes

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