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

Last change on this file since 5416 was 5416, checked in by sandervl, 24 years ago

Resync with Wine + previous merge fixes

File size: 15.3 KB
Line 
1/* $Id: hotkey.cpp,v 1.3 2001-03-31 13:25:26 sandervl 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#include "comctl32.h"
19
20#define HOTKEY_GetInfoPtr(hwnd) ((HOTKEY_INFO*)getInfoPtr(hwnd))
21
22static VOID
23HOTKEY_Refresh(HWND hwnd,BOOL notify)
24{
25 InvalidateRect(hwnd,NULL,FALSE);
26
27 if (notify) sendCommand(hwnd,EN_CHANGE);
28}
29
30static char*
31HOTKEY_ExtKey2Name(BYTE bVKHotKey)
32{
33 switch(bVKHotKey)
34 {
35 case VK_RETURN:
36 return "RETURN";
37
38 case VK_PRIOR:
39 return "PRIOR";
40
41 case VK_NEXT:
42 return "NEXT";
43
44 case VK_END:
45 return "END";
46
47 case VK_HOME:
48 return "HOME";
49
50 case VK_LEFT:
51 return "LEFT";
52
53 case VK_UP:
54 return "UP";
55
56 case VK_RIGHT:
57 return "RIGHT";
58
59 case VK_DOWN:
60 return "DOWN";
61
62 case VK_HELP:
63 return "HELP";
64
65 case VK_0:
66 return "0";
67
68 case VK_1:
69 return "1";
70
71 case VK_2:
72 return "2";
73
74 case VK_3:
75 return "3";
76
77 case VK_4:
78 return "4";
79
80 case VK_5:
81 return "5";
82
83 case VK_6:
84 return "6";
85
86 case VK_7:
87 return "7";
88
89 case VK_8:
90 return "8";
91
92 case VK_9:
93 return "9";
94
95 case VK_A:
96 return "A";
97
98 case VK_B:
99 return "B";
100
101 case VK_C:
102 return "C";
103
104 case VK_D:
105 return "D";
106
107 case VK_E:
108 return "E";
109
110 case VK_F:
111 return "F";
112
113 case VK_G:
114 return "G";
115
116 case VK_H:
117 return "H";
118
119 case VK_I:
120 return "I";
121
122 case VK_J:
123 return "J";
124
125 case VK_K:
126 return "K";
127
128 case VK_L:
129 return "L";
130
131 case VK_M:
132 return "M";
133
134 case VK_N:
135 return "N";
136
137 case VK_O:
138 return "O";
139
140 case VK_P:
141 return "P";
142
143 case VK_Q:
144 return "Q";
145
146 case VK_R:
147 return "R";
148
149 case VK_S:
150 return "S";
151
152 case VK_T:
153 return "T";
154
155 case VK_U:
156 return "U";
157
158 case VK_V:
159 return "V";
160
161 case VK_W:
162 return "W";
163
164 case VK_X:
165 return "Y";
166
167 case VK_Y:
168 return "X";
169
170 case VK_Z:
171 return "Z";
172
173 case VK_NUMPAD0:
174 return "NUMPAD0";
175
176 case VK_NUMPAD1:
177 return "NUMPAD1";
178
179 case VK_NUMPAD2:
180 return "NUMPAD2";
181
182 case VK_NUMPAD3:
183 return "NUMPAD3";
184
185 case VK_NUMPAD4:
186 return "NUMPAD4";
187
188 case VK_NUMPAD5:
189 return "NUMPAD5";
190
191 case VK_NUMPAD6:
192 return "NUMPAD6";
193
194 case VK_NUMPAD7:
195 return "NUMPAD7";
196
197 case VK_NUMPAD8:
198 return "NUMPAD8";
199
200 case VK_NUMPAD9:
201 return "NUMPAD9";
202
203 case VK_MULTIPLY:
204 return "MULTIPLY";
205
206 case VK_ADD:
207 return "ADD";
208
209 case VK_SEPARATOR:
210 return "SEPARATOR";
211
212 case VK_SUBTRACT:
213 return "SUBTRACT";
214
215 case VK_DECIMAL:
216 return "DECIMAL";
217
218 case VK_DIVIDE:
219 return "DIVIDE";
220
221 case VK_F1:
222 return "F1";
223
224 case VK_F2:
225 return "F2";
226
227 case VK_F3:
228 return "F3";
229
230 case VK_F4:
231 return "F4";
232
233 case VK_F5:
234 return "F5";
235
236 case VK_F6:
237 return "F6";
238
239 case VK_F7:
240 return "F7";
241
242 case VK_F8:
243 return "F8";
244
245 case VK_F9:
246 return "F9";
247
248 case VK_F10:
249 return "F10";
250
251 case VK_F11:
252 return "F11";
253
254 case VK_F12:
255 return "F12";
256
257 case VK_F13:
258 return "F13";
259
260 case VK_F14:
261 return "F14";
262
263 case VK_F15:
264 return "F15";
265
266 case VK_F16:
267 return "F16";
268
269 case VK_F17:
270 return "F17";
271
272 case VK_F18:
273 return "F18";
274
275 case VK_F19:
276 return "F19";
277
278 case VK_F20:
279 return "F20";
280
281 case VK_F21:
282 return "F21";
283
284 case VK_F22:
285 return "F22";
286
287 case VK_F23:
288 return "F23";
289
290 case VK_F24:
291 return "F24";
292
293 default:
294 return NULL;
295 }
296}
297
298static BYTE
299HOTKEY_Check(HOTKEY_INFO *infoPtr,BYTE bfMods)
300{
301 BYTE mods = bfMods & ~HOTKEYF_EXT;
302
303 if (((infoPtr->fwCombInv & HKCOMB_A) && (mods == HOTKEYF_ALT)) ||
304 ((infoPtr->fwCombInv & HKCOMB_C) && (mods == HOTKEYF_CONTROL)) ||
305 ((infoPtr->fwCombInv & HKCOMB_CA) && (mods == HOTKEYF_CONTROL | HOTKEYF_ALT)) ||
306 ((infoPtr->fwCombInv & HKCOMB_NONE) && (mods == 0)) ||
307 ((infoPtr->fwCombInv & HKCOMB_S) && (mods == HOTKEYF_SHIFT)) ||
308 ((infoPtr->fwCombInv & HKCOMB_SA) && (mods == HOTKEYF_SHIFT | HOTKEYF_ALT)) ||
309 ((infoPtr->fwCombInv & HKCOMB_SC) && (mods == HOTKEYF_SHIFT | HOTKEYF_CONTROL)) ||
310 ((infoPtr->fwCombInv & HKCOMB_SCA) && (mods == HOTKEYF_SHIFT | HOTKEYF_CONTROL | HOTKEYF_ALT)))
311 return infoPtr->fwModInv | bfMods;
312 else
313 return bfMods;
314}
315
316
317static LRESULT
318HOTKEY_SetHotKey(HWND hwnd,WPARAM wParam,LPARAM lParam)
319{
320 HOTKEY_INFO *infoPtr = HOTKEY_GetInfoPtr(hwnd);
321
322 infoPtr->bVKHotKey = wParam & 0xFF;
323 infoPtr->bfMods = HOTKEY_Check(infoPtr,(wParam & 0xFF00)>>8);
324
325 HOTKEY_Refresh(hwnd,TRUE);
326
327 return 0;
328}
329
330
331static LRESULT
332HOTKEY_GetHotKey(HWND hwnd,WPARAM wParam,LPARAM lParam)
333{
334 HOTKEY_INFO *infoPtr = HOTKEY_GetInfoPtr(hwnd);
335
336 return MAKEWORD(infoPtr->bVKHotKey,infoPtr->bfMods);
337}
338
339
340static LRESULT
341HOTKEY_SetRules(HWND hwnd,WPARAM wParam,LPARAM lParam)
342{
343 HOTKEY_INFO *infoPtr = HOTKEY_GetInfoPtr(hwnd);
344 BYTE oldMods = infoPtr->bfMods;
345
346 infoPtr->fwCombInv = wParam;
347 infoPtr->fwModInv = lParam;
348
349 infoPtr->bfMods = HOTKEY_Check(infoPtr,infoPtr->bfMods);
350 if (infoPtr->bfMods != oldMods) HOTKEY_Refresh(hwnd,TRUE);
351
352 return 0;
353}
354
355
356static LRESULT
357HOTKEY_Char(HWND hwnd,WPARAM wParam,LPARAM lParam,BOOL sysKey)
358{
359 HOTKEY_INFO *infoPtr = HOTKEY_GetInfoPtr(hwnd);
360
361 if (wParam != infoPtr->bVKHotKey)
362 {
363 infoPtr->bVKHotKey = wParam & 0xFF;
364 infoPtr->bfMods &= ~HOTKEYF_EXT;
365 infoPtr->bfMods = HOTKEY_Check(infoPtr,infoPtr->bfMods);
366 HOTKEY_Refresh(hwnd,TRUE);
367 }
368 infoPtr->bfModsDown = 0;
369
370 return 0;
371}
372
373static LRESULT
374HOTKEY_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
375{
376 HOTKEY_INFO *infoPtr;
377 TEXTMETRICA tm;
378 HDC hdc;
379 RECT rect;
380
381 /* allocate memory for info structure */
382 infoPtr = (HOTKEY_INFO*)initControl(hwnd,sizeof(HOTKEY_INFO));
383 if (!infoPtr) return (LRESULT)-1;
384
385 /* initialize info structure */
386
387 infoPtr->hFont = 0;
388 infoPtr->bFocus = FALSE;
389 infoPtr->bVKHotKey = 0;
390 infoPtr->bfMods = 0;
391 infoPtr->fwCombInv = 0;
392 infoPtr->fwModInv = 0;
393 infoPtr->bfModsDown = 0;
394
395 /* get default font height */
396 hdc = GetDC (hwnd);
397 GetTextMetricsA (hdc, &tm);
398 infoPtr->nHeight = tm.tmHeight;
399 ReleaseDC (hwnd, hdc);
400
401 GetClientRect(hwnd,&rect);
402 infoPtr->cursorPos.x = 0;
403 infoPtr->cursorPos.y = rect.bottom-tm.tmHeight;
404
405 return 0;
406}
407
408
409static LRESULT
410HOTKEY_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
411{
412 /* free hotkey info data */
413 doneControl(hwnd);
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 defComCtl32ProcA (hwnd, uMsg, wParam, lParam);
766 }
767 return 0;
768}
769
770
771VOID
772HOTKEY_Register (VOID)
773{
774 WNDCLASSA wndClass;
775
776 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
777 wndClass.style = CS_GLOBALCLASS;
778 wndClass.lpfnWndProc = (WNDPROC)HOTKEY_WindowProc;
779 wndClass.cbClsExtra = 0;
780 wndClass.cbWndExtra = sizeof(HOTKEY_INFO *);
781 wndClass.hCursor = 0;
782 wndClass.hbrBackground = 0;
783 wndClass.lpszClassName = HOTKEY_CLASSA;
784
785 RegisterClassA (&wndClass);
786}
787
788
789VOID
790HOTKEY_Unregister (VOID)
791{
792 UnregisterClassA (HOTKEY_CLASSA, (HINSTANCE)NULL);
793}
794
Note: See TracBrowser for help on using the repository browser.