Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenhotkey.c
Go to the documentation of this file.
00001 /* 00002 * Hotkey control 00003 * 00004 * Copyright 1998, 1999 Eric Kohl 00005 * Copyright 2002 Gyorgy 'Nog' Jeney 00006 * Copyright 2004 Robert Shearman 00007 * 00008 * This library is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Lesser General Public 00010 * License as published by the Free Software Foundation; either 00011 * version 2.1 of the License, or (at your option) any later version. 00012 * 00013 * This library is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License along with this library; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00021 * 00022 * This code was audited for completeness against the documented features 00023 * of Comctl32.dll version 6.0 on Sep. 21, 2004, by Robert Shearman. 00024 * 00025 * Unless otherwise noted, we believe this code to be complete, as per 00026 * the specification mentioned above. 00027 * If you discover missing features or bugs please note them below. 00028 * 00029 */ 00030 00031 #include <stdarg.h> 00032 #include <string.h> 00033 #include "windef.h" 00034 #include "winbase.h" 00035 #include "wingdi.h" 00036 #include "winuser.h" 00037 #include "winnls.h" 00038 #include "commctrl.h" 00039 #include "comctl32.h" 00040 #include "wine/debug.h" 00041 00042 WINE_DEFAULT_DEBUG_CHANNEL(hotkey); 00043 00044 typedef struct tagHOTKEY_INFO 00045 { 00046 HWND hwndSelf; 00047 HWND hwndNotify; 00048 HFONT hFont; 00049 BOOL bFocus; 00050 INT nHeight; 00051 WORD HotKey; 00052 WORD InvComb; 00053 WORD InvMod; 00054 BYTE CurrMod; 00055 INT CaretPos; 00056 DWORD ScanCode; 00057 WCHAR strNone[15]; /* hope it's long enough ... */ 00058 } HOTKEY_INFO; 00059 00060 static const WCHAR HOTKEY_plussep[] = { ' ', '+', ' ' }; 00061 static LRESULT HOTKEY_SetFont (HOTKEY_INFO *infoPtr, HFONT hFont, BOOL redraw); 00062 00063 #define IsOnlySet(flags) (infoPtr->CurrMod == (flags)) 00064 00065 static BOOL 00066 HOTKEY_IsCombInv(const HOTKEY_INFO *infoPtr) 00067 { 00068 TRACE("(infoPtr=%p)\n", infoPtr); 00069 if((infoPtr->InvComb & HKCOMB_NONE) && !infoPtr->CurrMod) 00070 return TRUE; 00071 if((infoPtr->InvComb & HKCOMB_S) && IsOnlySet(HOTKEYF_SHIFT)) 00072 return TRUE; 00073 if((infoPtr->InvComb & HKCOMB_C) && IsOnlySet(HOTKEYF_CONTROL)) 00074 return TRUE; 00075 if((infoPtr->InvComb & HKCOMB_A) && IsOnlySet(HOTKEYF_ALT)) 00076 return TRUE; 00077 if((infoPtr->InvComb & HKCOMB_SC) && 00078 IsOnlySet(HOTKEYF_SHIFT | HOTKEYF_CONTROL)) 00079 return TRUE; 00080 if((infoPtr->InvComb & HKCOMB_SA) && IsOnlySet(HOTKEYF_SHIFT | HOTKEYF_ALT)) 00081 return TRUE; 00082 if((infoPtr->InvComb & HKCOMB_CA) && 00083 IsOnlySet(HOTKEYF_CONTROL | HOTKEYF_ALT)) 00084 return TRUE; 00085 if((infoPtr->InvComb & HKCOMB_SCA) && 00086 IsOnlySet(HOTKEYF_SHIFT | HOTKEYF_CONTROL | HOTKEYF_ALT)) 00087 return TRUE; 00088 00089 TRACE("() Modifiers are valid\n"); 00090 return FALSE; 00091 } 00092 #undef IsOnlySet 00093 00094 static void 00095 HOTKEY_DrawHotKey(HOTKEY_INFO *infoPtr, HDC hdc, LPCWSTR KeyName, WORD NameLen) 00096 { 00097 SIZE TextSize; 00098 INT nXStart, nYStart; 00099 COLORREF clrOldText, clrOldBk; 00100 HFONT hFontOld; 00101 00102 /* Make a gap from the frame */ 00103 nXStart = GetSystemMetrics(SM_CXBORDER); 00104 nYStart = GetSystemMetrics(SM_CYBORDER); 00105 00106 hFontOld = SelectObject(hdc, infoPtr->hFont); 00107 if (GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE) & WS_DISABLED) 00108 { 00109 clrOldText = SetTextColor(hdc, comctl32_color.clrGrayText); 00110 clrOldBk = SetBkColor(hdc, comctl32_color.clrBtnFace); 00111 } 00112 else 00113 { 00114 clrOldText = SetTextColor(hdc, comctl32_color.clrWindowText); 00115 clrOldBk = SetBkColor(hdc, comctl32_color.clrWindow); 00116 } 00117 00118 TextOutW(hdc, nXStart, nYStart, KeyName, NameLen); 00119 00120 /* Get the text width for the caret */ 00121 GetTextExtentPoint32W(hdc, KeyName, NameLen, &TextSize); 00122 infoPtr->CaretPos = nXStart + TextSize.cx; 00123 00124 SetBkColor(hdc, clrOldBk); 00125 SetTextColor(hdc, clrOldText); 00126 SelectObject(hdc, hFontOld); 00127 00128 /* position the caret */ 00129 SetCaretPos(infoPtr->CaretPos, nYStart); 00130 } 00131 00132 /* Draw the names of the keys in the control */ 00133 static void 00134 HOTKEY_Refresh(HOTKEY_INFO *infoPtr, HDC hdc) 00135 { 00136 WCHAR KeyName[64]; 00137 WORD NameLen = 0; 00138 BYTE Modifier; 00139 00140 TRACE("(infoPtr=%p hdc=%p)\n", infoPtr, hdc); 00141 00142 if(!infoPtr->CurrMod && !infoPtr->HotKey) { 00143 HOTKEY_DrawHotKey (infoPtr, hdc, infoPtr->strNone, 4); 00144 return; 00145 } 00146 00147 if(infoPtr->HotKey) 00148 Modifier = HIBYTE(infoPtr->HotKey); 00149 else if(HOTKEY_IsCombInv(infoPtr)) 00150 Modifier = infoPtr->InvMod; 00151 else 00152 Modifier = infoPtr->CurrMod; 00153 00154 if(Modifier & HOTKEYF_CONTROL) { 00155 GetKeyNameTextW(MAKELPARAM(0, MapVirtualKeyW(VK_CONTROL, 0)), 00156 KeyName, 64); 00157 NameLen = lstrlenW(KeyName); 00158 memcpy(&KeyName[NameLen], HOTKEY_plussep, sizeof(HOTKEY_plussep)); 00159 NameLen += 3; 00160 } 00161 if(Modifier & HOTKEYF_SHIFT) { 00162 GetKeyNameTextW(MAKELPARAM(0, MapVirtualKeyW(VK_SHIFT, 0)), 00163 &KeyName[NameLen], 64 - NameLen); 00164 NameLen = lstrlenW(KeyName); 00165 memcpy(&KeyName[NameLen], HOTKEY_plussep, sizeof(HOTKEY_plussep)); 00166 NameLen += 3; 00167 } 00168 if(Modifier & HOTKEYF_ALT) { 00169 GetKeyNameTextW(MAKELPARAM(0, MapVirtualKeyW(VK_MENU, 0)), 00170 &KeyName[NameLen], 64 - NameLen); 00171 NameLen = lstrlenW(KeyName); 00172 memcpy(&KeyName[NameLen], HOTKEY_plussep, sizeof(HOTKEY_plussep)); 00173 NameLen += 3; 00174 } 00175 00176 if(infoPtr->HotKey) { 00177 GetKeyNameTextW(infoPtr->ScanCode, &KeyName[NameLen], 64 - NameLen); 00178 NameLen = lstrlenW(KeyName); 00179 } 00180 else 00181 KeyName[NameLen] = 0; 00182 00183 HOTKEY_DrawHotKey (infoPtr, hdc, KeyName, NameLen); 00184 } 00185 00186 static void 00187 HOTKEY_Paint(HOTKEY_INFO *infoPtr, HDC hdc) 00188 { 00189 if (hdc) 00190 HOTKEY_Refresh(infoPtr, hdc); 00191 else { 00192 PAINTSTRUCT ps; 00193 hdc = BeginPaint (infoPtr->hwndSelf, &ps); 00194 HOTKEY_Refresh (infoPtr, hdc); 00195 EndPaint (infoPtr->hwndSelf, &ps); 00196 } 00197 } 00198 00199 static LRESULT 00200 HOTKEY_GetHotKey(const HOTKEY_INFO *infoPtr) 00201 { 00202 TRACE("(infoPtr=%p) Modifiers: 0x%x, Virtual Key: %d\n", infoPtr, 00203 HIBYTE(infoPtr->HotKey), LOBYTE(infoPtr->HotKey)); 00204 return (LRESULT)infoPtr->HotKey; 00205 } 00206 00207 static void 00208 HOTKEY_SetHotKey(HOTKEY_INFO *infoPtr, WORD hotKey) 00209 { 00210 infoPtr->HotKey = hotKey; 00211 infoPtr->ScanCode = 00212 MAKELPARAM(0, MapVirtualKeyW(LOBYTE(infoPtr->HotKey), 0)); 00213 TRACE("(infoPtr=%p hotKey=%x) Modifiers: 0x%x, Virtual Key: %d\n", infoPtr, 00214 hotKey, HIBYTE(infoPtr->HotKey), LOBYTE(infoPtr->HotKey)); 00215 InvalidateRect(infoPtr->hwndSelf, NULL, TRUE); 00216 } 00217 00218 static void 00219 HOTKEY_SetRules(HOTKEY_INFO *infoPtr, WORD invComb, WORD invMod) 00220 { 00221 infoPtr->InvComb = invComb; 00222 infoPtr->InvMod = invMod; 00223 TRACE("(infoPtr=%p) Invalid Modifers: 0x%x, If Invalid: 0x%x\n", infoPtr, 00224 infoPtr->InvComb, infoPtr->InvMod); 00225 } 00226 00227 00228 static LRESULT 00229 HOTKEY_Create (HOTKEY_INFO *infoPtr, const CREATESTRUCTW *lpcs) 00230 { 00231 infoPtr->hwndNotify = lpcs->hwndParent; 00232 00233 HOTKEY_SetFont(infoPtr, GetStockObject(SYSTEM_FONT), 0); 00234 00235 return 0; 00236 } 00237 00238 00239 static LRESULT 00240 HOTKEY_Destroy (HOTKEY_INFO *infoPtr) 00241 { 00242 /* free hotkey info data */ 00243 SetWindowLongPtrW (infoPtr->hwndSelf, 0, 0); 00244 Free (infoPtr); 00245 return 0; 00246 } 00247 00248 00249 static LRESULT 00250 HOTKEY_EraseBackground (const HOTKEY_INFO *infoPtr, HDC hdc) 00251 { 00252 HBRUSH hBrush, hSolidBrush = NULL; 00253 RECT rc; 00254 00255 if (GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE) & WS_DISABLED) 00256 hBrush = hSolidBrush = CreateSolidBrush(comctl32_color.clrBtnFace); 00257 else 00258 { 00259 hBrush = (HBRUSH)SendMessageW(infoPtr->hwndNotify, WM_CTLCOLOREDIT, 00260 (WPARAM)hdc, (LPARAM)infoPtr->hwndSelf); 00261 if (!hBrush) 00262 hBrush = hSolidBrush = CreateSolidBrush(comctl32_color.clrWindow); 00263 } 00264 00265 GetClientRect (infoPtr->hwndSelf, &rc); 00266 00267 FillRect (hdc, &rc, hBrush); 00268 00269 if (hSolidBrush) 00270 DeleteObject(hSolidBrush); 00271 00272 return -1; 00273 } 00274 00275 00276 static inline LRESULT 00277 HOTKEY_GetFont (const HOTKEY_INFO *infoPtr) 00278 { 00279 return (LRESULT)infoPtr->hFont; 00280 } 00281 00282 static LRESULT 00283 HOTKEY_KeyDown (HOTKEY_INFO *infoPtr, DWORD key, DWORD flags) 00284 { 00285 WORD wOldHotKey; 00286 BYTE bOldMod; 00287 00288 if (GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE) & WS_DISABLED) 00289 return 0; 00290 00291 TRACE("() Key: %d\n", key); 00292 00293 wOldHotKey = infoPtr->HotKey; 00294 bOldMod = infoPtr->CurrMod; 00295 00296 /* If any key is Pressed, we have to reset the hotkey in the control */ 00297 infoPtr->HotKey = 0; 00298 00299 switch (key) 00300 { 00301 case VK_RETURN: 00302 case VK_TAB: 00303 case VK_SPACE: 00304 case VK_DELETE: 00305 case VK_ESCAPE: 00306 case VK_BACK: 00307 InvalidateRect(infoPtr->hwndSelf, NULL, TRUE); 00308 return DefWindowProcW (infoPtr->hwndSelf, WM_KEYDOWN, key, flags); 00309 00310 case VK_SHIFT: 00311 infoPtr->CurrMod |= HOTKEYF_SHIFT; 00312 break; 00313 case VK_CONTROL: 00314 infoPtr->CurrMod |= HOTKEYF_CONTROL; 00315 break; 00316 case VK_MENU: 00317 infoPtr->CurrMod |= HOTKEYF_ALT; 00318 break; 00319 00320 default: 00321 if(HOTKEY_IsCombInv(infoPtr)) 00322 infoPtr->HotKey = MAKEWORD(key, infoPtr->InvMod); 00323 else 00324 infoPtr->HotKey = MAKEWORD(key, infoPtr->CurrMod); 00325 infoPtr->ScanCode = flags; 00326 break; 00327 } 00328 00329 if ((wOldHotKey != infoPtr->HotKey) || (bOldMod != infoPtr->CurrMod)) 00330 { 00331 InvalidateRect(infoPtr->hwndSelf, NULL, TRUE); 00332 00333 /* send EN_CHANGE notification */ 00334 SendMessageW(infoPtr->hwndNotify, WM_COMMAND, 00335 MAKEWPARAM(GetDlgCtrlID(infoPtr->hwndSelf), EN_CHANGE), 00336 (LPARAM)infoPtr->hwndSelf); 00337 } 00338 00339 return 0; 00340 } 00341 00342 00343 static LRESULT 00344 HOTKEY_KeyUp (HOTKEY_INFO *infoPtr, DWORD key) 00345 { 00346 BYTE bOldMod; 00347 00348 if (GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE) & WS_DISABLED) 00349 return 0; 00350 00351 TRACE("() Key: %d\n", key); 00352 00353 bOldMod = infoPtr->CurrMod; 00354 00355 switch (key) 00356 { 00357 case VK_SHIFT: 00358 infoPtr->CurrMod &= ~HOTKEYF_SHIFT; 00359 break; 00360 case VK_CONTROL: 00361 infoPtr->CurrMod &= ~HOTKEYF_CONTROL; 00362 break; 00363 case VK_MENU: 00364 infoPtr->CurrMod &= ~HOTKEYF_ALT; 00365 break; 00366 default: 00367 return 1; 00368 } 00369 00370 if (bOldMod != infoPtr->CurrMod) 00371 { 00372 InvalidateRect(infoPtr->hwndSelf, NULL, TRUE); 00373 00374 /* send EN_CHANGE notification */ 00375 SendMessageW(infoPtr->hwndNotify, WM_COMMAND, 00376 MAKEWPARAM(GetDlgCtrlID(infoPtr->hwndSelf), EN_CHANGE), 00377 (LPARAM)infoPtr->hwndSelf); 00378 } 00379 00380 return 0; 00381 } 00382 00383 00384 static LRESULT 00385 HOTKEY_KillFocus (HOTKEY_INFO *infoPtr) 00386 { 00387 infoPtr->bFocus = FALSE; 00388 DestroyCaret (); 00389 00390 return 0; 00391 } 00392 00393 00394 static LRESULT 00395 HOTKEY_LButtonDown (const HOTKEY_INFO *infoPtr) 00396 { 00397 if (!(GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE) & WS_DISABLED)) 00398 SetFocus (infoPtr->hwndSelf); 00399 00400 return 0; 00401 } 00402 00403 00404 static inline LRESULT 00405 HOTKEY_NCCreate (HWND hwnd, const CREATESTRUCTW *lpcs) 00406 { 00407 HOTKEY_INFO *infoPtr; 00408 DWORD dwExStyle = GetWindowLongW (hwnd, GWL_EXSTYLE); 00409 SetWindowLongW (hwnd, GWL_EXSTYLE, 00410 dwExStyle | WS_EX_CLIENTEDGE); 00411 00412 /* allocate memory for info structure */ 00413 infoPtr = Alloc (sizeof(HOTKEY_INFO)); 00414 SetWindowLongPtrW(hwnd, 0, (DWORD_PTR)infoPtr); 00415 00416 /* initialize info structure */ 00417 infoPtr->HotKey = infoPtr->InvComb = infoPtr->InvMod = infoPtr->CurrMod = 0; 00418 infoPtr->CaretPos = GetSystemMetrics(SM_CXBORDER); 00419 infoPtr->hwndSelf = hwnd; 00420 LoadStringW(COMCTL32_hModule, HKY_NONE, infoPtr->strNone, 15); 00421 00422 return DefWindowProcW (infoPtr->hwndSelf, WM_NCCREATE, 0, (LPARAM)lpcs); 00423 } 00424 00425 static LRESULT 00426 HOTKEY_SetFocus (HOTKEY_INFO *infoPtr) 00427 { 00428 infoPtr->bFocus = TRUE; 00429 00430 CreateCaret (infoPtr->hwndSelf, NULL, 1, infoPtr->nHeight); 00431 SetCaretPos (infoPtr->CaretPos, GetSystemMetrics(SM_CYBORDER)); 00432 ShowCaret (infoPtr->hwndSelf); 00433 00434 return 0; 00435 } 00436 00437 00438 static LRESULT 00439 HOTKEY_SetFont (HOTKEY_INFO *infoPtr, HFONT hFont, BOOL redraw) 00440 { 00441 TEXTMETRICW tm; 00442 HDC hdc; 00443 HFONT hOldFont = 0; 00444 00445 infoPtr->hFont = hFont; 00446 00447 hdc = GetDC (infoPtr->hwndSelf); 00448 if (infoPtr->hFont) 00449 hOldFont = SelectObject (hdc, infoPtr->hFont); 00450 00451 GetTextMetricsW (hdc, &tm); 00452 infoPtr->nHeight = tm.tmHeight; 00453 00454 if (infoPtr->hFont) 00455 SelectObject (hdc, hOldFont); 00456 ReleaseDC (infoPtr->hwndSelf, hdc); 00457 00458 if (redraw) 00459 InvalidateRect (infoPtr->hwndSelf, NULL, TRUE); 00460 00461 return 0; 00462 } 00463 00464 static LRESULT WINAPI 00465 HOTKEY_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 00466 { 00467 HOTKEY_INFO *infoPtr = (HOTKEY_INFO *)GetWindowLongPtrW (hwnd, 0); 00468 TRACE("hwnd=%p msg=%x wparam=%lx lparam=%lx\n", hwnd, uMsg, wParam, lParam); 00469 if (!infoPtr && (uMsg != WM_NCCREATE)) 00470 return DefWindowProcW (hwnd, uMsg, wParam, lParam); 00471 switch (uMsg) 00472 { 00473 case HKM_GETHOTKEY: 00474 return HOTKEY_GetHotKey (infoPtr); 00475 case HKM_SETHOTKEY: 00476 HOTKEY_SetHotKey (infoPtr, (WORD)wParam); 00477 break; 00478 case HKM_SETRULES: 00479 HOTKEY_SetRules (infoPtr, (WORD)wParam, (WORD)lParam); 00480 break; 00481 00482 case WM_CHAR: 00483 case WM_SYSCHAR: 00484 return HOTKEY_KeyDown (infoPtr, MapVirtualKeyW(LOBYTE(HIWORD(lParam)), 1), lParam); 00485 00486 case WM_CREATE: 00487 return HOTKEY_Create (infoPtr, (LPCREATESTRUCTW)lParam); 00488 00489 case WM_DESTROY: 00490 return HOTKEY_Destroy (infoPtr); 00491 00492 case WM_ERASEBKGND: 00493 return HOTKEY_EraseBackground (infoPtr, (HDC)wParam); 00494 00495 case WM_GETDLGCODE: 00496 return DLGC_WANTCHARS | DLGC_WANTARROWS; 00497 00498 case WM_GETFONT: 00499 return HOTKEY_GetFont (infoPtr); 00500 00501 case WM_KEYDOWN: 00502 case WM_SYSKEYDOWN: 00503 return HOTKEY_KeyDown (infoPtr, wParam, lParam); 00504 00505 case WM_KEYUP: 00506 case WM_SYSKEYUP: 00507 return HOTKEY_KeyUp (infoPtr, wParam); 00508 00509 case WM_KILLFOCUS: 00510 return HOTKEY_KillFocus (infoPtr); 00511 00512 case WM_LBUTTONDOWN: 00513 return HOTKEY_LButtonDown (infoPtr); 00514 00515 case WM_NCCREATE: 00516 return HOTKEY_NCCreate (hwnd, (LPCREATESTRUCTW)lParam); 00517 00518 case WM_PRINTCLIENT: 00519 case WM_PAINT: 00520 HOTKEY_Paint(infoPtr, (HDC)wParam); 00521 return 0; 00522 00523 case WM_SETFOCUS: 00524 return HOTKEY_SetFocus (infoPtr); 00525 00526 case WM_SETFONT: 00527 return HOTKEY_SetFont (infoPtr, (HFONT)wParam, LOWORD(lParam)); 00528 00529 default: 00530 if ((uMsg >= WM_USER) && (uMsg < WM_APP) && !COMCTL32_IsReflectedMessage(uMsg)) 00531 ERR("unknown msg %04x wp=%08lx lp=%08lx\n", 00532 uMsg, wParam, lParam); 00533 return DefWindowProcW (hwnd, uMsg, wParam, lParam); 00534 } 00535 return 0; 00536 } 00537 00538 00539 void 00540 HOTKEY_Register (void) 00541 { 00542 WNDCLASSW wndClass; 00543 00544 ZeroMemory (&wndClass, sizeof(WNDCLASSW)); 00545 wndClass.style = CS_GLOBALCLASS; 00546 wndClass.lpfnWndProc = HOTKEY_WindowProc; 00547 wndClass.cbClsExtra = 0; 00548 wndClass.cbWndExtra = sizeof(HOTKEY_INFO *); 00549 wndClass.hCursor = 0; 00550 wndClass.hbrBackground = 0; 00551 wndClass.lpszClassName = HOTKEY_CLASSW; 00552 00553 RegisterClassW (&wndClass); 00554 } 00555 00556 00557 void 00558 HOTKEY_Unregister (void) 00559 { 00560 UnregisterClassW (HOTKEY_CLASSW, NULL); 00561 } Generated on Sun May 27 2012 04:23:00 for ReactOS by
1.7.6.1
|