4 * Copyright 1998, 1999 Eric Kohl
5 * Copyright 2002 Gyorgy 'Nog' Jeney
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * - What are we meant to do with the WM_CHAR message?
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(hotkey
);
38 typedef struct tagHOTKEY_INFO
50 WCHAR strNone
[15]; /* hope its long enough ... */
53 #define HOTKEY_GetInfoPtr(hwnd) ((HOTKEY_INFO *)GetWindowLongA (hwnd, 0))
55 static const WCHAR HOTKEY_plussep
[] = { ' ', '+', ' ' };
57 #define IsOnlySet(flags) (infoPtr->CurrMod == (flags))
60 HOTKEY_IsCombInv(HOTKEY_INFO
*infoPtr
)
62 TRACE("(infoPtr=%p)\n", infoPtr
);
63 if((infoPtr
->InvComb
& HKCOMB_NONE
) && !infoPtr
->CurrMod
)
65 if((infoPtr
->InvComb
& HKCOMB_S
) && IsOnlySet(HOTKEYF_SHIFT
))
67 if((infoPtr
->InvComb
& HKCOMB_C
) && IsOnlySet(HOTKEYF_CONTROL
))
69 if((infoPtr
->InvComb
& HKCOMB_A
) && IsOnlySet(HOTKEYF_ALT
))
71 if((infoPtr
->InvComb
& HKCOMB_SC
) &&
72 IsOnlySet(HOTKEYF_SHIFT
| HOTKEYF_CONTROL
))
74 if((infoPtr
->InvComb
& HKCOMB_SA
) && IsOnlySet(HOTKEYF_SHIFT
| HOTKEYF_ALT
))
76 if((infoPtr
->InvComb
& HKCOMB_CA
) &&
77 IsOnlySet(HOTKEYF_CONTROL
| HOTKEYF_ALT
))
79 if((infoPtr
->InvComb
& HKCOMB_SCA
) &&
80 IsOnlySet(HOTKEYF_SHIFT
| HOTKEYF_CONTROL
| HOTKEYF_ALT
))
83 TRACE("() Modifiers are valid\n");
89 HOTKEY_DrawHotKey(HOTKEY_INFO
*infoPtr
, LPCWSTR KeyName
, WORD NameLen
,
93 DWORD dwExStyle
= GetWindowLongW (infoPtr
->hwndSelf
, GWL_EXSTYLE
);
95 /* We have to allow some space for the frame to be drawn */
98 DrawTextW(hdc
, KeyName
, NameLen
, rc
, DT_LEFT
| DT_VCENTER
);
101 if(dwExStyle
& WS_EX_CLIENTEDGE
)
102 DrawEdge(hdc
, rc
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
104 /* Get the text size and position the caret accordingly */
105 GetTextExtentPoint32W (hdc
, KeyName
, NameLen
, &TextSize
);
106 infoPtr
->CaretPos
= TextSize
.cx
+ 2;
107 SetCaretPos(infoPtr
->CaretPos
, 3);
110 /* Draw the names of the keys in the control */
112 HOTKEY_Refresh(HOTKEY_INFO
*infoPtr
, HDC hdc
)
114 WCHAR KeyName
[sizeof(WCHAR
) * 64];
119 GetClientRect(infoPtr
->hwndSelf
, &rc
);
121 TRACE("(infoPtr=%p hdc=%p)\n", infoPtr
, hdc
);
123 if(!infoPtr
->CurrMod
&& !infoPtr
->HotKey
) {
124 HOTKEY_DrawHotKey (infoPtr
, infoPtr
->strNone
, 4, &rc
, hdc
);
129 Modifier
= HIBYTE(infoPtr
->HotKey
);
130 else if(HOTKEY_IsCombInv(infoPtr
))
131 Modifier
= infoPtr
->InvMod
;
133 Modifier
= infoPtr
->CurrMod
;
135 if(Modifier
& HOTKEYF_CONTROL
) {
136 GetKeyNameTextW(MAKELPARAM(0, MapVirtualKeyW(VK_CONTROL
, 0)),
138 NameLen
= lstrlenW(KeyName
);
139 memcpy(&KeyName
[NameLen
], HOTKEY_plussep
, sizeof(HOTKEY_plussep
));
142 if(Modifier
& HOTKEYF_SHIFT
) {
143 GetKeyNameTextW(MAKELPARAM(0, MapVirtualKeyW(VK_SHIFT
, 0)),
144 &KeyName
[NameLen
], 64 - NameLen
);
145 NameLen
= lstrlenW(KeyName
);
146 memcpy(&KeyName
[NameLen
], HOTKEY_plussep
, sizeof(HOTKEY_plussep
));
149 if(Modifier
& HOTKEYF_ALT
) {
150 GetKeyNameTextW(MAKELPARAM(0, MapVirtualKeyW(VK_MENU
, 0)),
151 &KeyName
[NameLen
], 64 - NameLen
);
152 NameLen
= lstrlenW(KeyName
);
153 memcpy(&KeyName
[NameLen
], HOTKEY_plussep
, sizeof(HOTKEY_plussep
));
157 if(infoPtr
->HotKey
) {
158 GetKeyNameTextW(infoPtr
->ScanCode
, &KeyName
[NameLen
], 64 - NameLen
);
159 NameLen
= lstrlenW(KeyName
);
162 KeyName
[NameLen
] = 0;
164 HOTKEY_DrawHotKey (infoPtr
, KeyName
, NameLen
, &rc
, hdc
);
168 HOTKEY_Paint(HOTKEY_INFO
*infoPtr
, HDC hdc
)
171 HOTKEY_Refresh(infoPtr
, hdc
);
174 hdc
= BeginPaint (infoPtr
->hwndSelf
, &ps
);
175 HOTKEY_Refresh (infoPtr
, hdc
);
176 EndPaint (infoPtr
->hwndSelf
, &ps
);
181 HOTKEY_GetHotKey(HOTKEY_INFO
*infoPtr
)
183 TRACE("(infoPtr=%p) Modifiers: 0x%x, Virtual Key: %d\n", infoPtr
,
184 HIBYTE(infoPtr
->HotKey
), LOBYTE(infoPtr
->HotKey
));
185 return (LRESULT
)infoPtr
->HotKey
;
189 HOTKEY_SetHotKey(HOTKEY_INFO
*infoPtr
, WPARAM wParam
)
191 infoPtr
->HotKey
= (WORD
)wParam
;
193 MAKELPARAM(0, MapVirtualKeyW(LOBYTE(infoPtr
->HotKey
), 0));
194 TRACE("(infoPtr=%p wParam=%x) Modifiers: 0x%x, Virtual Key: %d\n", infoPtr
,
195 wParam
, HIBYTE(infoPtr
->HotKey
), LOBYTE(infoPtr
->HotKey
));
196 InvalidateRect(infoPtr
->hwndSelf
, NULL
, TRUE
);
200 HOTKEY_SetRules(HOTKEY_INFO
*infoPtr
, WPARAM wParam
, LPARAM lParam
)
202 infoPtr
->InvComb
= (WORD
)wParam
;
203 infoPtr
->InvMod
= (WORD
)lParam
;
204 TRACE("(infoPtr=%p) Invalid Modifers: 0x%x, If Invalid: 0x%x\n", infoPtr
,
205 infoPtr
->InvComb
, infoPtr
->InvMod
);
208 /* << HOTKEY_Char >> */
211 HOTKEY_Create (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
213 HOTKEY_INFO
*infoPtr
;
217 /* allocate memory for info structure */
218 infoPtr
= (HOTKEY_INFO
*)Alloc (sizeof(HOTKEY_INFO
));
219 SetWindowLongW (hwnd
, 0, (DWORD
)infoPtr
);
221 /* initialize info structure */
222 infoPtr
->HotKey
= infoPtr
->InvComb
= infoPtr
->InvMod
= infoPtr
->CurrMod
= 0;
223 infoPtr
->CaretPos
= 2;
224 infoPtr
->hwndSelf
= hwnd
;
225 LoadStringW(COMCTL32_hModule
, HKY_NONE
, infoPtr
->strNone
, 15);
227 /* get default font height */
229 GetTextMetricsW (hdc
, &tm
);
230 infoPtr
->nHeight
= tm
.tmHeight
;
231 ReleaseDC (hwnd
, hdc
);
238 HOTKEY_Destroy (HOTKEY_INFO
*infoPtr
, WPARAM wParam
, LPARAM lParam
)
240 HWND hwnd
= infoPtr
->hwndSelf
;
241 /* free hotkey info data */
243 SetWindowLongW (hwnd
, 0, 0);
249 HOTKEY_EraseBackground (HOTKEY_INFO
*infoPtr
, WPARAM wParam
, LPARAM lParam
)
255 (HBRUSH
)SendMessageW (GetParent (infoPtr
->hwndSelf
), WM_CTLCOLOREDIT
,
256 wParam
, (LPARAM
)infoPtr
->hwndSelf
);
258 hBrush
= (HBRUSH
)GetStockObject (WHITE_BRUSH
);
259 GetClientRect (infoPtr
->hwndSelf
, &rc
);
261 FillRect ((HDC
)wParam
, &rc
, hBrush
);
267 inline static LRESULT
268 HOTKEY_GetFont (HOTKEY_INFO
*infoPtr
, WPARAM wParam
, LPARAM lParam
)
270 return (LRESULT
)infoPtr
->hFont
;
274 HOTKEY_KeyDown (HOTKEY_INFO
*infoPtr
, WPARAM wParam
, LPARAM lParam
)
276 TRACE("() Key: %d\n", wParam
);
277 /* If any key is Pressed, we have to reset the hotkey in the control */
287 InvalidateRect(infoPtr
->hwndSelf
, NULL
, TRUE
);
288 return DefWindowProcW (infoPtr
->hwndSelf
, WM_KEYDOWN
, wParam
,
292 infoPtr
->CurrMod
|= HOTKEYF_SHIFT
;
295 infoPtr
->CurrMod
|= HOTKEYF_CONTROL
;
298 infoPtr
->CurrMod
|= HOTKEYF_ALT
;
302 if(HOTKEY_IsCombInv(infoPtr
))
303 infoPtr
->HotKey
= MAKEWORD(wParam
, infoPtr
->InvMod
);
305 infoPtr
->HotKey
= MAKEWORD(wParam
, infoPtr
->CurrMod
);
306 infoPtr
->ScanCode
= lParam
;
310 InvalidateRect(infoPtr
->hwndSelf
, NULL
, TRUE
);
316 HOTKEY_KeyUp (HOTKEY_INFO
*infoPtr
, WPARAM wParam
, LPARAM lParam
)
318 TRACE("() Key: %d\n", wParam
);
321 infoPtr
->CurrMod
&= ~HOTKEYF_SHIFT
;
324 infoPtr
->CurrMod
&= ~HOTKEYF_CONTROL
;
327 infoPtr
->CurrMod
&= ~HOTKEYF_ALT
;
333 InvalidateRect(infoPtr
->hwndSelf
, NULL
, TRUE
);
340 HOTKEY_KillFocus (HOTKEY_INFO
*infoPtr
, WPARAM wParam
, LPARAM lParam
)
342 infoPtr
->bFocus
= FALSE
;
350 HOTKEY_LButtonDown (HOTKEY_INFO
*infoPtr
, WPARAM wParam
, LPARAM lParam
)
352 SetFocus (infoPtr
->hwndSelf
);
358 inline static LRESULT
359 HOTKEY_NCCreate (HOTKEY_INFO
*infoPtr
, WPARAM wParam
, LPARAM lParam
)
361 DWORD dwExStyle
= GetWindowLongW (infoPtr
->hwndSelf
, GWL_EXSTYLE
);
362 SetWindowLongW (infoPtr
->hwndSelf
, GWL_EXSTYLE
,
363 dwExStyle
| WS_EX_CLIENTEDGE
);
364 return DefWindowProcW (infoPtr
->hwndSelf
, WM_NCCREATE
, wParam
, lParam
);
368 HOTKEY_SetFocus (HOTKEY_INFO
*infoPtr
, WPARAM wParam
, LPARAM lParam
)
370 infoPtr
->bFocus
= TRUE
;
373 CreateCaret (infoPtr
->hwndSelf
, NULL
, 1, infoPtr
->nHeight
- 2);
375 SetCaretPos (infoPtr
->CaretPos
, 3);
377 ShowCaret (infoPtr
->hwndSelf
);
384 inline static LRESULT
385 HOTKEY_SetFont (HOTKEY_INFO
*infoPtr
, WPARAM wParam
, LPARAM lParam
)
391 infoPtr
->hFont
= (HFONT
)wParam
;
393 hdc
= GetDC (infoPtr
->hwndSelf
);
395 hOldFont
= SelectObject (hdc
, infoPtr
->hFont
);
397 GetTextMetricsW (hdc
, &tm
);
398 infoPtr
->nHeight
= tm
.tmHeight
;
401 SelectObject (hdc
, hOldFont
);
402 ReleaseDC (infoPtr
->hwndSelf
, hdc
);
405 InvalidateRect (infoPtr
->hwndSelf
, NULL
, TRUE
);
410 static LRESULT WINAPI
411 HOTKEY_WindowProc (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
413 HOTKEY_INFO
*infoPtr
= HOTKEY_GetInfoPtr (hwnd
);
414 TRACE("hwnd=%p msg=%x wparam=%x lparam=%lx\n", hwnd
, uMsg
, wParam
, lParam
);
415 if (!infoPtr
&& (uMsg
!= WM_CREATE
))
416 return DefWindowProcW (hwnd
, uMsg
, wParam
, lParam
);
420 return HOTKEY_GetHotKey (infoPtr
);
422 HOTKEY_SetHotKey (infoPtr
, wParam
);
425 HOTKEY_SetRules (infoPtr
, wParam
, lParam
);
431 return HOTKEY_Create (hwnd
, wParam
, lParam
);
434 return HOTKEY_Destroy (infoPtr
, wParam
, lParam
);
437 return HOTKEY_EraseBackground (infoPtr
, wParam
, lParam
);
440 return DLGC_WANTCHARS
| DLGC_WANTARROWS
;
443 return HOTKEY_GetFont (infoPtr
, wParam
, lParam
);
447 return HOTKEY_KeyDown (infoPtr
, wParam
, lParam
);
451 return HOTKEY_KeyUp (infoPtr
, wParam
, lParam
);
454 return HOTKEY_KillFocus (infoPtr
, wParam
, lParam
);
457 return HOTKEY_LButtonDown (infoPtr
, wParam
, lParam
);
460 return HOTKEY_NCCreate (infoPtr
, wParam
, lParam
);
463 HOTKEY_Paint(infoPtr
, (HDC
)wParam
);
467 return HOTKEY_SetFocus (infoPtr
, wParam
, lParam
);
470 return HOTKEY_SetFont (infoPtr
, wParam
, lParam
);
472 /* case WM_SYSCHAR: */
475 if ((uMsg
>= WM_USER
) && (uMsg
< WM_APP
))
476 ERR("unknown msg %04x wp=%08x lp=%08lx\n",
477 uMsg
, wParam
, lParam
);
478 return DefWindowProcW (hwnd
, uMsg
, wParam
, lParam
);
485 HOTKEY_Register (void)
489 ZeroMemory (&wndClass
, sizeof(WNDCLASSW
));
490 wndClass
.style
= CS_GLOBALCLASS
;
491 wndClass
.lpfnWndProc
= (WNDPROC
)HOTKEY_WindowProc
;
492 wndClass
.cbClsExtra
= 0;
493 wndClass
.cbWndExtra
= sizeof(HOTKEY_INFO
*);
494 wndClass
.hCursor
= 0;
495 wndClass
.hbrBackground
= 0;
496 wndClass
.lpszClassName
= HOTKEY_CLASSW
;
498 RegisterClassW (&wndClass
);
503 HOTKEY_Unregister (void)
505 UnregisterClassW (HOTKEY_CLASSW
, NULL
);