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
51 WCHAR strNone
[15]; /* hope its long enough ... */
54 #define HOTKEY_GetInfoPtr(hwnd) ((HOTKEY_INFO *)GetWindowLongPtrA (hwnd, 0))
56 static const WCHAR HOTKEY_plussep
[] = { ' ', '+', ' ' };
58 #define IsOnlySet(flags) (infoPtr->CurrMod == (flags))
61 HOTKEY_IsCombInv(HOTKEY_INFO
*infoPtr
)
63 TRACE("(infoPtr=%p)\n", infoPtr
);
64 if((infoPtr
->InvComb
& HKCOMB_NONE
) && !infoPtr
->CurrMod
)
66 if((infoPtr
->InvComb
& HKCOMB_S
) && IsOnlySet(HOTKEYF_SHIFT
))
68 if((infoPtr
->InvComb
& HKCOMB_C
) && IsOnlySet(HOTKEYF_CONTROL
))
70 if((infoPtr
->InvComb
& HKCOMB_A
) && IsOnlySet(HOTKEYF_ALT
))
72 if((infoPtr
->InvComb
& HKCOMB_SC
) &&
73 IsOnlySet(HOTKEYF_SHIFT
| HOTKEYF_CONTROL
))
75 if((infoPtr
->InvComb
& HKCOMB_SA
) && IsOnlySet(HOTKEYF_SHIFT
| HOTKEYF_ALT
))
77 if((infoPtr
->InvComb
& HKCOMB_CA
) &&
78 IsOnlySet(HOTKEYF_CONTROL
| HOTKEYF_ALT
))
80 if((infoPtr
->InvComb
& HKCOMB_SCA
) &&
81 IsOnlySet(HOTKEYF_SHIFT
| HOTKEYF_CONTROL
| HOTKEYF_ALT
))
84 TRACE("() Modifiers are valid\n");
90 HOTKEY_DrawHotKey(HOTKEY_INFO
*infoPtr
, LPCWSTR KeyName
, WORD NameLen
,
94 DWORD dwExStyle
= GetWindowLongW (infoPtr
->hwndSelf
, GWL_EXSTYLE
);
96 /* We have to allow some space for the frame to be drawn */
99 DrawTextW(hdc
, KeyName
, NameLen
, rc
, DT_LEFT
| DT_VCENTER
);
102 if(dwExStyle
& WS_EX_CLIENTEDGE
)
103 DrawEdge(hdc
, rc
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
105 /* Get the text size and position the caret accordingly */
106 GetTextExtentPoint32W (hdc
, KeyName
, NameLen
, &TextSize
);
107 infoPtr
->CaretPos
= TextSize
.cx
+ 2;
108 SetCaretPos(infoPtr
->CaretPos
, 3);
111 /* Draw the names of the keys in the control */
113 HOTKEY_Refresh(HOTKEY_INFO
*infoPtr
, HDC hdc
)
115 WCHAR KeyName
[sizeof(WCHAR
) * 64];
120 GetClientRect(infoPtr
->hwndSelf
, &rc
);
122 TRACE("(infoPtr=%p hdc=%p)\n", infoPtr
, hdc
);
124 if(!infoPtr
->CurrMod
&& !infoPtr
->HotKey
) {
125 HOTKEY_DrawHotKey (infoPtr
, infoPtr
->strNone
, 4, &rc
, hdc
);
130 Modifier
= HIBYTE(infoPtr
->HotKey
);
131 else if(HOTKEY_IsCombInv(infoPtr
))
132 Modifier
= infoPtr
->InvMod
;
134 Modifier
= infoPtr
->CurrMod
;
136 if(Modifier
& HOTKEYF_CONTROL
) {
137 GetKeyNameTextW(MAKELPARAM(0, MapVirtualKeyW(VK_CONTROL
, 0)),
139 NameLen
= lstrlenW(KeyName
);
140 memcpy(&KeyName
[NameLen
], HOTKEY_plussep
, sizeof(HOTKEY_plussep
));
143 if(Modifier
& HOTKEYF_SHIFT
) {
144 GetKeyNameTextW(MAKELPARAM(0, MapVirtualKeyW(VK_SHIFT
, 0)),
145 &KeyName
[NameLen
], 64 - NameLen
);
146 NameLen
= lstrlenW(KeyName
);
147 memcpy(&KeyName
[NameLen
], HOTKEY_plussep
, sizeof(HOTKEY_plussep
));
150 if(Modifier
& HOTKEYF_ALT
) {
151 GetKeyNameTextW(MAKELPARAM(0, MapVirtualKeyW(VK_MENU
, 0)),
152 &KeyName
[NameLen
], 64 - NameLen
);
153 NameLen
= lstrlenW(KeyName
);
154 memcpy(&KeyName
[NameLen
], HOTKEY_plussep
, sizeof(HOTKEY_plussep
));
158 if(infoPtr
->HotKey
) {
159 GetKeyNameTextW(infoPtr
->ScanCode
, &KeyName
[NameLen
], 64 - NameLen
);
160 NameLen
= lstrlenW(KeyName
);
163 KeyName
[NameLen
] = 0;
165 HOTKEY_DrawHotKey (infoPtr
, KeyName
, NameLen
, &rc
, hdc
);
169 HOTKEY_Paint(HOTKEY_INFO
*infoPtr
, HDC hdc
)
172 HOTKEY_Refresh(infoPtr
, hdc
);
175 hdc
= BeginPaint (infoPtr
->hwndSelf
, &ps
);
176 HOTKEY_Refresh (infoPtr
, hdc
);
177 EndPaint (infoPtr
->hwndSelf
, &ps
);
182 HOTKEY_GetHotKey(HOTKEY_INFO
*infoPtr
)
184 TRACE("(infoPtr=%p) Modifiers: 0x%x, Virtual Key: %d\n", infoPtr
,
185 HIBYTE(infoPtr
->HotKey
), LOBYTE(infoPtr
->HotKey
));
186 return (LRESULT
)infoPtr
->HotKey
;
190 HOTKEY_SetHotKey(HOTKEY_INFO
*infoPtr
, WPARAM wParam
)
192 infoPtr
->HotKey
= (WORD
)wParam
;
194 MAKELPARAM(0, MapVirtualKeyW(LOBYTE(infoPtr
->HotKey
), 0));
195 TRACE("(infoPtr=%p wParam=%x) Modifiers: 0x%x, Virtual Key: %d\n", infoPtr
,
196 wParam
, HIBYTE(infoPtr
->HotKey
), LOBYTE(infoPtr
->HotKey
));
197 InvalidateRect(infoPtr
->hwndSelf
, NULL
, TRUE
);
201 HOTKEY_SetRules(HOTKEY_INFO
*infoPtr
, WPARAM wParam
, LPARAM lParam
)
203 infoPtr
->InvComb
= (WORD
)wParam
;
204 infoPtr
->InvMod
= (WORD
)lParam
;
205 TRACE("(infoPtr=%p) Invalid Modifers: 0x%x, If Invalid: 0x%x\n", infoPtr
,
206 infoPtr
->InvComb
, infoPtr
->InvMod
);
209 /* << HOTKEY_Char >> */
212 HOTKEY_Create (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
214 HOTKEY_INFO
*infoPtr
;
218 /* allocate memory for info structure */
219 infoPtr
= (HOTKEY_INFO
*)Alloc (sizeof(HOTKEY_INFO
));
220 SetWindowLongPtrW (hwnd
, 0, (DWORD_PTR
)infoPtr
);
222 /* initialize info structure */
223 infoPtr
->HotKey
= infoPtr
->InvComb
= infoPtr
->InvMod
= infoPtr
->CurrMod
= 0;
224 infoPtr
->CaretPos
= 2;
225 infoPtr
->hwndSelf
= hwnd
;
226 infoPtr
->hwndNotify
= ((LPCREATESTRUCTA
)lParam
)->hwndParent
;
227 LoadStringW(COMCTL32_hModule
, HKY_NONE
, infoPtr
->strNone
, 15);
229 /* get default font height */
231 GetTextMetricsW (hdc
, &tm
);
232 infoPtr
->nHeight
= tm
.tmHeight
;
233 ReleaseDC (hwnd
, hdc
);
240 HOTKEY_Destroy (HOTKEY_INFO
*infoPtr
, WPARAM wParam
, LPARAM lParam
)
242 HWND hwnd
= infoPtr
->hwndSelf
;
243 /* free hotkey info data */
245 SetWindowLongPtrW (hwnd
, 0, 0);
251 HOTKEY_EraseBackground (HOTKEY_INFO
*infoPtr
, WPARAM wParam
, LPARAM lParam
)
257 (HBRUSH
)SendMessageW (infoPtr
->hwndNotify
, WM_CTLCOLOREDIT
,
258 wParam
, (LPARAM
)infoPtr
->hwndSelf
);
260 hBrush
= (HBRUSH
)GetStockObject (WHITE_BRUSH
);
261 GetClientRect (infoPtr
->hwndSelf
, &rc
);
263 FillRect ((HDC
)wParam
, &rc
, hBrush
);
269 inline static LRESULT
270 HOTKEY_GetFont (HOTKEY_INFO
*infoPtr
, WPARAM wParam
, LPARAM lParam
)
272 return (LRESULT
)infoPtr
->hFont
;
276 HOTKEY_KeyDown (HOTKEY_INFO
*infoPtr
, WPARAM wParam
, LPARAM lParam
)
278 TRACE("() Key: %d\n", wParam
);
279 /* If any key is Pressed, we have to reset the hotkey in the control */
289 InvalidateRect(infoPtr
->hwndSelf
, NULL
, TRUE
);
290 return DefWindowProcW (infoPtr
->hwndSelf
, WM_KEYDOWN
, wParam
,
294 infoPtr
->CurrMod
|= HOTKEYF_SHIFT
;
297 infoPtr
->CurrMod
|= HOTKEYF_CONTROL
;
300 infoPtr
->CurrMod
|= HOTKEYF_ALT
;
304 if(HOTKEY_IsCombInv(infoPtr
))
305 infoPtr
->HotKey
= MAKEWORD(wParam
, infoPtr
->InvMod
);
307 infoPtr
->HotKey
= MAKEWORD(wParam
, infoPtr
->CurrMod
);
308 infoPtr
->ScanCode
= lParam
;
312 InvalidateRect(infoPtr
->hwndSelf
, NULL
, TRUE
);
318 HOTKEY_KeyUp (HOTKEY_INFO
*infoPtr
, WPARAM wParam
, LPARAM lParam
)
320 TRACE("() Key: %d\n", wParam
);
323 infoPtr
->CurrMod
&= ~HOTKEYF_SHIFT
;
326 infoPtr
->CurrMod
&= ~HOTKEYF_CONTROL
;
329 infoPtr
->CurrMod
&= ~HOTKEYF_ALT
;
335 InvalidateRect(infoPtr
->hwndSelf
, NULL
, TRUE
);
342 HOTKEY_KillFocus (HOTKEY_INFO
*infoPtr
, WPARAM wParam
, LPARAM lParam
)
344 infoPtr
->bFocus
= FALSE
;
352 HOTKEY_LButtonDown (HOTKEY_INFO
*infoPtr
, WPARAM wParam
, LPARAM lParam
)
354 SetFocus (infoPtr
->hwndSelf
);
360 inline static LRESULT
361 HOTKEY_NCCreate (HOTKEY_INFO
*infoPtr
, WPARAM wParam
, LPARAM lParam
)
363 DWORD dwExStyle
= GetWindowLongW (infoPtr
->hwndSelf
, GWL_EXSTYLE
);
364 SetWindowLongW (infoPtr
->hwndSelf
, GWL_EXSTYLE
,
365 dwExStyle
| WS_EX_CLIENTEDGE
);
366 return DefWindowProcW (infoPtr
->hwndSelf
, WM_NCCREATE
, wParam
, lParam
);
370 HOTKEY_SetFocus (HOTKEY_INFO
*infoPtr
, WPARAM wParam
, LPARAM lParam
)
372 infoPtr
->bFocus
= TRUE
;
375 CreateCaret (infoPtr
->hwndSelf
, NULL
, 1, infoPtr
->nHeight
- 2);
377 SetCaretPos (infoPtr
->CaretPos
, 3);
379 ShowCaret (infoPtr
->hwndSelf
);
386 inline static LRESULT
387 HOTKEY_SetFont (HOTKEY_INFO
*infoPtr
, WPARAM wParam
, LPARAM lParam
)
393 infoPtr
->hFont
= (HFONT
)wParam
;
395 hdc
= GetDC (infoPtr
->hwndSelf
);
397 hOldFont
= SelectObject (hdc
, infoPtr
->hFont
);
399 GetTextMetricsW (hdc
, &tm
);
400 infoPtr
->nHeight
= tm
.tmHeight
;
403 SelectObject (hdc
, hOldFont
);
404 ReleaseDC (infoPtr
->hwndSelf
, hdc
);
407 InvalidateRect (infoPtr
->hwndSelf
, NULL
, TRUE
);
412 static LRESULT WINAPI
413 HOTKEY_WindowProc (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
415 HOTKEY_INFO
*infoPtr
= HOTKEY_GetInfoPtr (hwnd
);
416 TRACE("hwnd=%p msg=%x wparam=%x lparam=%lx\n", hwnd
, uMsg
, wParam
, lParam
);
417 if (!infoPtr
&& (uMsg
!= WM_CREATE
))
418 return DefWindowProcW (hwnd
, uMsg
, wParam
, lParam
);
422 return HOTKEY_GetHotKey (infoPtr
);
424 HOTKEY_SetHotKey (infoPtr
, wParam
);
427 HOTKEY_SetRules (infoPtr
, wParam
, lParam
);
433 return HOTKEY_Create (hwnd
, wParam
, lParam
);
436 return HOTKEY_Destroy (infoPtr
, wParam
, lParam
);
439 return HOTKEY_EraseBackground (infoPtr
, wParam
, lParam
);
442 return DLGC_WANTCHARS
| DLGC_WANTARROWS
;
445 return HOTKEY_GetFont (infoPtr
, wParam
, lParam
);
449 return HOTKEY_KeyDown (infoPtr
, wParam
, lParam
);
453 return HOTKEY_KeyUp (infoPtr
, wParam
, lParam
);
456 return HOTKEY_KillFocus (infoPtr
, wParam
, lParam
);
459 return HOTKEY_LButtonDown (infoPtr
, wParam
, lParam
);
462 return HOTKEY_NCCreate (infoPtr
, wParam
, lParam
);
465 HOTKEY_Paint(infoPtr
, (HDC
)wParam
);
469 return HOTKEY_SetFocus (infoPtr
, wParam
, lParam
);
472 return HOTKEY_SetFont (infoPtr
, wParam
, lParam
);
474 /* case WM_SYSCHAR: */
477 if ((uMsg
>= WM_USER
) && (uMsg
< WM_APP
))
478 ERR("unknown msg %04x wp=%08x lp=%08lx\n",
479 uMsg
, wParam
, lParam
);
480 return DefWindowProcW (hwnd
, uMsg
, wParam
, lParam
);
487 HOTKEY_Register (void)
491 ZeroMemory (&wndClass
, sizeof(WNDCLASSW
));
492 wndClass
.style
= CS_GLOBALCLASS
;
493 wndClass
.lpfnWndProc
= (WNDPROC
)HOTKEY_WindowProc
;
494 wndClass
.cbClsExtra
= 0;
495 wndClass
.cbWndExtra
= sizeof(HOTKEY_INFO
*);
496 wndClass
.hCursor
= 0;
497 wndClass
.hbrBackground
= 0;
498 wndClass
.lpszClassName
= HOTKEY_CLASSW
;
500 RegisterClassW (&wndClass
);
505 HOTKEY_Unregister (void)
507 UnregisterClassW (HOTKEY_CLASSW
, NULL
);