ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

hotkey.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.