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=%x)\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 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, (HBITMAP)0, 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=%x 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, (HINSTANCE)NULL);