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?
29 #include "wine/debug.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(hotkey
);
33 typedef struct tagHOTKEY_INFO
45 WCHAR strNone
[15]; /* hope its long enough ... */
48 #define HOTKEY_GetInfoPtr(hwnd) ((HOTKEY_INFO *)GetWindowLongA (hwnd, 0))
50 static const WCHAR HOTKEY_plussep
[] = { ' ', '+', ' ' };
52 #define IsOnlySet(flags) (infoPtr->CurrMod == (flags))
55 HOTKEY_IsCombInv(HOTKEY_INFO
*infoPtr
)
57 TRACE("(infoPtr=%p)\n", infoPtr
);
58 if((infoPtr
->InvComb
& HKCOMB_NONE
) && !infoPtr
->CurrMod
)
60 if((infoPtr
->InvComb
& HKCOMB_S
) && IsOnlySet(HOTKEYF_SHIFT
))
62 if((infoPtr
->InvComb
& HKCOMB_C
) && IsOnlySet(HOTKEYF_CONTROL
))
64 if((infoPtr
->InvComb
& HKCOMB_A
) && IsOnlySet(HOTKEYF_ALT
))
66 if((infoPtr
->InvComb
& HKCOMB_SC
) &&
67 IsOnlySet(HOTKEYF_SHIFT
| HOTKEYF_CONTROL
))
69 if((infoPtr
->InvComb
& HKCOMB_SA
) && IsOnlySet(HOTKEYF_SHIFT
| HOTKEYF_ALT
))
71 if((infoPtr
->InvComb
& HKCOMB_CA
) &&
72 IsOnlySet(HOTKEYF_CONTROL
| HOTKEYF_ALT
))
74 if((infoPtr
->InvComb
& HKCOMB_SCA
) &&
75 IsOnlySet(HOTKEYF_SHIFT
| HOTKEYF_CONTROL
| HOTKEYF_ALT
))
78 TRACE("() Modifiers are valid\n");
84 HOTKEY_DrawHotKey(HOTKEY_INFO
*infoPtr
, LPCWSTR KeyName
, WORD NameLen
,
88 DWORD dwExStyle
= GetWindowLongW (infoPtr
->hwndSelf
, GWL_EXSTYLE
);
90 /* We have to allow some space for the frame to be drawn */
93 DrawTextW(hdc
, KeyName
, NameLen
, rc
, DT_LEFT
| DT_VCENTER
);
96 if(dwExStyle
& WS_EX_CLIENTEDGE
)
97 DrawEdge(hdc
, rc
, EDGE_SUNKEN
, BF_RECT
| BF_ADJUST
);
99 /* Get the text size and position the caret accordingly */
100 GetTextExtentPoint32W (hdc
, KeyName
, NameLen
, &TextSize
);
101 infoPtr
->CaretPos
= TextSize
.cx
+ 2;
102 SetCaretPos(infoPtr
->CaretPos
, 3);
105 /* Draw the names of the keys in the control */
107 HOTKEY_Refresh(HOTKEY_INFO
*infoPtr
, HDC hdc
)
109 WCHAR KeyName
[sizeof(WCHAR
) * 64];
114 GetClientRect(infoPtr
->hwndSelf
, &rc
);
116 TRACE("(infoPtr=%p hdc=%p)\n", infoPtr
, hdc
);
118 if(!infoPtr
->CurrMod
&& !infoPtr
->HotKey
) {
119 HOTKEY_DrawHotKey (infoPtr
, infoPtr
->strNone
, 4, &rc
, hdc
);
124 Modifier
= HIBYTE(infoPtr
->HotKey
);
125 else if(HOTKEY_IsCombInv(infoPtr
))
126 Modifier
= infoPtr
->InvMod
;
128 Modifier
= infoPtr
->CurrMod
;
130 if(Modifier
& HOTKEYF_CONTROL
) {
131 GetKeyNameTextW(MAKELPARAM(0, MapVirtualKeyW(VK_CONTROL
, 0)),
133 NameLen
= lstrlenW(KeyName
);
134 memcpy(&KeyName
[NameLen
], HOTKEY_plussep
, sizeof(HOTKEY_plussep
));
137 if(Modifier
& HOTKEYF_SHIFT
) {
138 GetKeyNameTextW(MAKELPARAM(0, MapVirtualKeyW(VK_SHIFT
, 0)),
139 &KeyName
[NameLen
], 64 - NameLen
);
140 NameLen
= lstrlenW(KeyName
);
141 memcpy(&KeyName
[NameLen
], HOTKEY_plussep
, sizeof(HOTKEY_plussep
));
144 if(Modifier
& HOTKEYF_ALT
) {
145 GetKeyNameTextW(MAKELPARAM(0, MapVirtualKeyW(VK_MENU
, 0)),
146 &KeyName
[NameLen
], 64 - NameLen
);
147 NameLen
= lstrlenW(KeyName
);
148 memcpy(&KeyName
[NameLen
], HOTKEY_plussep
, sizeof(HOTKEY_plussep
));
152 if(infoPtr
->HotKey
) {
153 GetKeyNameTextW(infoPtr
->ScanCode
, &KeyName
[NameLen
], 64 - NameLen
);
154 NameLen
= lstrlenW(KeyName
);
157 KeyName
[NameLen
] = 0;
159 HOTKEY_DrawHotKey (infoPtr
, KeyName
, NameLen
, &rc
, hdc
);
163 HOTKEY_Paint(HOTKEY_INFO
*infoPtr
, HDC hdc
)
166 HOTKEY_Refresh(infoPtr
, hdc
);
169 hdc
= BeginPaint (infoPtr
->hwndSelf
, &ps
);
170 HOTKEY_Refresh (infoPtr
, hdc
);
171 EndPaint (infoPtr
->hwndSelf
, &ps
);
176 HOTKEY_GetHotKey(HOTKEY_INFO
*infoPtr
)
178 TRACE("(infoPtr=%p) Modifiers: 0x%x, Virtual Key: %d\n", infoPtr
,
179 HIBYTE(infoPtr
->HotKey
), LOBYTE(infoPtr
->HotKey
));
180 return (LRESULT
)infoPtr
->HotKey
;
184 HOTKEY_SetHotKey(HOTKEY_INFO
*infoPtr
, WPARAM wParam
)
186 infoPtr
->HotKey
= (WORD
)wParam
;
188 MAKELPARAM(0, MapVirtualKeyW(LOBYTE(infoPtr
->HotKey
), 0));
189 TRACE("(infoPtr=%p wParam=%x) Modifiers: 0x%x, Virtual Key: %d\n", infoPtr
,
190 wParam
, HIBYTE(infoPtr
->HotKey
), LOBYTE(infoPtr
->HotKey
));
191 InvalidateRect(infoPtr
->hwndSelf
, NULL
, TRUE
);
195 HOTKEY_SetRules(HOTKEY_INFO
*infoPtr
, WPARAM wParam
, LPARAM lParam
)
197 infoPtr
->InvComb
= (WORD
)wParam
;
198 infoPtr
->InvMod
= (WORD
)lParam
;
199 TRACE("(infoPtr=%p) Invalid Modifers: 0x%x, If Invalid: 0x%x\n", infoPtr
,
200 infoPtr
->InvComb
, infoPtr
->InvMod
);
203 /* << HOTKEY_Char >> */
206 HOTKEY_Create (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
208 HOTKEY_INFO
*infoPtr
;
212 /* allocate memory for info structure */
213 infoPtr
= (HOTKEY_INFO
*)COMCTL32_Alloc (sizeof(HOTKEY_INFO
));
214 SetWindowLongW (hwnd
, 0, (DWORD
)infoPtr
);
216 /* initialize info structure */
217 infoPtr
->HotKey
= infoPtr
->InvComb
= infoPtr
->InvMod
= infoPtr
->CurrMod
= 0;
218 infoPtr
->CaretPos
= 2;
219 infoPtr
->hwndSelf
= hwnd
;
220 LoadStringW(COMCTL32_hModule
, HKY_NONE
, infoPtr
->strNone
, 15);
222 /* get default font height */
224 GetTextMetricsW (hdc
, &tm
);
225 infoPtr
->nHeight
= tm
.tmHeight
;
226 ReleaseDC (hwnd
, hdc
);
233 HOTKEY_Destroy (HOTKEY_INFO
*infoPtr
, WPARAM wParam
, LPARAM lParam
)
235 HWND hwnd
= infoPtr
->hwndSelf
;
236 /* free hotkey info data */
237 COMCTL32_Free (infoPtr
);
238 SetWindowLongW (hwnd
, 0, 0);
244 HOTKEY_EraseBackground (HOTKEY_INFO
*infoPtr
, WPARAM wParam
, LPARAM lParam
)
250 (HBRUSH
)SendMessageW (GetParent (infoPtr
->hwndSelf
), WM_CTLCOLOREDIT
,
251 wParam
, (LPARAM
)infoPtr
->hwndSelf
);
253 hBrush
= (HBRUSH
)GetStockObject (WHITE_BRUSH
);
254 GetClientRect (infoPtr
->hwndSelf
, &rc
);
256 FillRect ((HDC
)wParam
, &rc
, hBrush
);
262 inline static LRESULT
263 HOTKEY_GetFont (HOTKEY_INFO
*infoPtr
, WPARAM wParam
, LPARAM lParam
)
265 return (LRESULT
)infoPtr
->hFont
;
269 HOTKEY_KeyDown (HOTKEY_INFO
*infoPtr
, WPARAM wParam
, LPARAM lParam
)
271 TRACE("() Key: %d\n", wParam
);
272 /* If any key is Pressed, we have to reset the hotkey in the control */
282 InvalidateRect(infoPtr
->hwndSelf
, NULL
, TRUE
);
283 return DefWindowProcW (infoPtr
->hwndSelf
, WM_KEYDOWN
, wParam
,
287 infoPtr
->CurrMod
|= HOTKEYF_SHIFT
;
290 infoPtr
->CurrMod
|= HOTKEYF_CONTROL
;
293 infoPtr
->CurrMod
|= HOTKEYF_ALT
;
297 if(HOTKEY_IsCombInv(infoPtr
))
298 infoPtr
->HotKey
= MAKEWORD(wParam
, infoPtr
->InvMod
);
300 infoPtr
->HotKey
= MAKEWORD(wParam
, infoPtr
->CurrMod
);
301 infoPtr
->ScanCode
= lParam
;
305 InvalidateRect(infoPtr
->hwndSelf
, NULL
, TRUE
);
311 HOTKEY_KeyUp (HOTKEY_INFO
*infoPtr
, WPARAM wParam
, LPARAM lParam
)
313 TRACE("() Key: %d\n", wParam
);
316 infoPtr
->CurrMod
&= ~HOTKEYF_SHIFT
;
319 infoPtr
->CurrMod
&= ~HOTKEYF_CONTROL
;
322 infoPtr
->CurrMod
&= ~HOTKEYF_ALT
;
328 InvalidateRect(infoPtr
->hwndSelf
, NULL
, TRUE
);
335 HOTKEY_KillFocus (HOTKEY_INFO
*infoPtr
, WPARAM wParam
, LPARAM lParam
)
337 infoPtr
->bFocus
= FALSE
;
345 HOTKEY_LButtonDown (HOTKEY_INFO
*infoPtr
, WPARAM wParam
, LPARAM lParam
)
347 SetFocus (infoPtr
->hwndSelf
);
353 inline static LRESULT
354 HOTKEY_NCCreate (HOTKEY_INFO
*infoPtr
, WPARAM wParam
, LPARAM lParam
)
356 DWORD dwExStyle
= GetWindowLongW (infoPtr
->hwndSelf
, GWL_EXSTYLE
);
357 SetWindowLongW (infoPtr
->hwndSelf
, GWL_EXSTYLE
,
358 dwExStyle
| WS_EX_CLIENTEDGE
);
359 return DefWindowProcW (infoPtr
->hwndSelf
, WM_NCCREATE
, wParam
, lParam
);
363 HOTKEY_SetFocus (HOTKEY_INFO
*infoPtr
, WPARAM wParam
, LPARAM lParam
)
365 infoPtr
->bFocus
= TRUE
;
368 CreateCaret (infoPtr
->hwndSelf
, NULL
, 1, infoPtr
->nHeight
- 2);
370 SetCaretPos (infoPtr
->CaretPos
, 3);
372 ShowCaret (infoPtr
->hwndSelf
);
379 inline static LRESULT
380 HOTKEY_SetFont (HOTKEY_INFO
*infoPtr
, WPARAM wParam
, LPARAM lParam
)
386 infoPtr
->hFont
= (HFONT
)wParam
;
388 hdc
= GetDC (infoPtr
->hwndSelf
);
390 hOldFont
= SelectObject (hdc
, infoPtr
->hFont
);
392 GetTextMetricsW (hdc
, &tm
);
393 infoPtr
->nHeight
= tm
.tmHeight
;
396 SelectObject (hdc
, hOldFont
);
397 ReleaseDC (infoPtr
->hwndSelf
, hdc
);
400 InvalidateRect (infoPtr
->hwndSelf
, NULL
, TRUE
);
405 static LRESULT WINAPI
406 HOTKEY_WindowProc (HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
408 HOTKEY_INFO
*infoPtr
= HOTKEY_GetInfoPtr (hwnd
);
409 TRACE("hwnd=%p msg=%x wparam=%x lparam=%lx\n", hwnd
, uMsg
, wParam
, lParam
);
410 if (!infoPtr
&& (uMsg
!= WM_CREATE
))
411 return DefWindowProcW (hwnd
, uMsg
, wParam
, lParam
);
415 return HOTKEY_GetHotKey (infoPtr
);
417 HOTKEY_SetHotKey (infoPtr
, wParam
);
420 HOTKEY_SetRules (infoPtr
, wParam
, lParam
);
426 return HOTKEY_Create (hwnd
, wParam
, lParam
);
429 return HOTKEY_Destroy (infoPtr
, wParam
, lParam
);
432 return HOTKEY_EraseBackground (infoPtr
, wParam
, lParam
);
435 return DLGC_WANTCHARS
| DLGC_WANTARROWS
;
438 return HOTKEY_GetFont (infoPtr
, wParam
, lParam
);
442 return HOTKEY_KeyDown (infoPtr
, wParam
, lParam
);
446 return HOTKEY_KeyUp (infoPtr
, wParam
, lParam
);
449 return HOTKEY_KillFocus (infoPtr
, wParam
, lParam
);
452 return HOTKEY_LButtonDown (infoPtr
, wParam
, lParam
);
455 return HOTKEY_NCCreate (infoPtr
, wParam
, lParam
);
458 HOTKEY_Paint(infoPtr
, (HDC
)wParam
);
462 return HOTKEY_SetFocus (infoPtr
, wParam
, lParam
);
465 return HOTKEY_SetFont (infoPtr
, wParam
, lParam
);
467 /* case WM_SYSCHAR: */
470 if ((uMsg
>= WM_USER
) && (uMsg
< WM_APP
))
471 ERR("unknown msg %04x wp=%08x lp=%08lx\n",
472 uMsg
, wParam
, lParam
);
473 return DefWindowProcW (hwnd
, uMsg
, wParam
, lParam
);
480 HOTKEY_Register (void)
484 ZeroMemory (&wndClass
, sizeof(WNDCLASSW
));
485 wndClass
.style
= CS_GLOBALCLASS
;
486 wndClass
.lpfnWndProc
= (WNDPROC
)HOTKEY_WindowProc
;
487 wndClass
.cbClsExtra
= 0;
488 wndClass
.cbWndExtra
= sizeof(HOTKEY_INFO
*);
489 wndClass
.hCursor
= 0;
490 wndClass
.hbrBackground
= 0;
491 wndClass
.lpszClassName
= HOTKEY_CLASSW
;
493 RegisterClassW (&wndClass
);
498 HOTKEY_Unregister (void)
500 UnregisterClassW (HOTKEY_CLASSW
, NULL
);