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);