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 *)GetWindowLongA (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 SetWindowLongW (hwnd, 0, (DWORD)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 SetWindowLongW (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);