hotkey.c
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 10k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. /*-----------------------------------------------------------------------
  2. **
  3. ** Hotkey.c
  4. **
  5. ** Hotkey edit control.
  6. **
  7. **-----------------------------------------------------------------------*/
  8. //
  9. // Win32 REVIEW:
  10. //  See all the Get/SetWindowInt().
  11. //
  12. #include "ctlspriv.h"
  13. #define F_EXT       0x01000000L
  14. #define GWU_VIRTKEY  0
  15. #define GWU_MODS     1*sizeof(ULONG_PTR)
  16. #define GWU_INVALID  2*sizeof(ULONG_PTR)
  17. #define GWU_DEFAULT  3*sizeof(ULONG_PTR)
  18. #define GWU_HFONT    4*sizeof(ULONG_PTR)
  19. #define GWU_YFONT    5*sizeof(ULONG_PTR)
  20. #define NUM_WND_EXTRA (GWU_YFONT+sizeof(ULONG_PTR))
  21. LRESULT CALLBACK HotKeyWndProc(HWND hwnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
  22. #ifndef WIN32
  23. #pragma code_seg(CODESEG_INIT)
  24. #endif
  25. BOOL FAR PASCAL InitHotKeyClass(HINSTANCE hInstance)
  26. {
  27.     WNDCLASS wc;
  28.     if (!GetClassInfo(hInstance, HOTKEY_CLASS, &wc))
  29.     {
  30. #ifndef WIN32
  31.         extern LRESULT CALLBACK _HotKeyWndProc(HWND, UINT, WPARAM, LPARAM);
  32.         wc.lpfnWndProc   = _HotKeyWndProc;
  33. #else
  34.         wc.lpfnWndProc   = HotKeyWndProc;
  35. #endif
  36.         wc.lpszClassName = s_szHOTKEY_CLASS;
  37.         wc.style         = CS_GLOBALCLASS;
  38.         wc.hInstance     = hInstance;
  39.         wc.hIcon         = NULL;
  40.         wc.hCursor       = NULL;
  41.         wc.hbrBackground = NULL;
  42.         wc.lpszMenuName  = NULL;
  43.         wc.cbClsExtra    = 0;
  44.         wc.cbWndExtra    = NUM_WND_EXTRA;
  45.         if (!RegisterClass(&wc))
  46.             return FALSE;
  47.     }
  48.     return TRUE;
  49. }
  50. #ifndef WIN32
  51. #pragma code_seg()
  52. #endif
  53. #ifndef WINNT
  54. #pragma data_seg(DATASEG_READONLY)
  55. #endif
  56. const UINT s_Combos[8] = {
  57.                     HKCOMB_NONE,
  58.                     HKCOMB_S,
  59.                     HKCOMB_C,
  60.                     HKCOMB_SC,
  61.                     HKCOMB_A,
  62.                     HKCOMB_SA,
  63.                     HKCOMB_CA,
  64.                     HKCOMB_SCA};
  65. #ifndef WINNT
  66. #pragma data_seg()
  67. #endif
  68. void NEAR PASCAL SetHotKey(HWND hwnd, WORD wVirtKey, WORD wMods, BOOL fSendNotify)
  69. {
  70.     /* don't invalidate if it's the same
  71.      */
  72.     if (wVirtKey == GetWindowInt(hwnd, GWU_VIRTKEY) &&
  73.         wMods == GetWindowInt(hwnd, GWU_MODS))
  74.         return;
  75.     SetWindowInt(hwnd, GWU_VIRTKEY ,wVirtKey);
  76.     SetWindowInt(hwnd, GWU_MODS ,wMods);
  77.     InvalidateRect(hwnd,NULL,TRUE);
  78.     if (fSendNotify) {
  79.         FORWARD_WM_COMMAND(GetParent(hwnd), GetDlgCtrlID(hwnd), hwnd, EN_CHANGE, SendMessage);
  80.     }
  81.     MyNotifyWinEvent(EVENT_OBJECT_VALUECHANGE, hwnd, OBJID_CLIENT, 0);
  82. }
  83. void NEAR PASCAL GetKeyName(UINT vk, LPTSTR lpsz, BOOL fExt)
  84. {
  85.     LONG scan;
  86.     scan = (LONG)MapVirtualKey(vk,0) << 16;
  87.     if (fExt)
  88.         scan |= F_EXT;
  89.     GetKeyNameText(scan,lpsz,50);
  90. }
  91. void NEAR PASCAL PaintHotKey(register HWND hwnd)
  92. {
  93.     TCHAR sz[128];
  94.     TCHAR szPlus[10];
  95.     int cch;
  96.     register HDC hdc;
  97.     UINT wMods;
  98.     UINT wVirtKey;
  99.     PAINTSTRUCT ps;
  100.     int x, y;
  101.     HANDLE hFont;
  102.     // DWORD dwColor;
  103.     // DWORD dwBkColor;
  104.     LocalizedLoadString(IDS_PLUS, szPlus, ARRAYSIZE(szPlus));
  105.     wVirtKey = (UINT) GetWindowInt(hwnd, GWU_VIRTKEY);
  106.     wMods = (UINT) GetWindowInt(hwnd, GWU_MODS);
  107.     if (wVirtKey || wMods)
  108.     {
  109.         sz[0] = 0;
  110.         cch = 0;
  111.         if (wMods & HOTKEYF_CONTROL)
  112.         {
  113.             GetKeyName(VK_CONTROL, sz, FALSE);
  114.             lstrcat(sz,(LPTSTR)szPlus);
  115.         }
  116.         if (wMods & HOTKEYF_SHIFT)
  117.         {
  118.             GetKeyName(VK_SHIFT, sz+lstrlen(sz), FALSE);
  119.             lstrcat(sz,szPlus);
  120.         }
  121.         if (wMods & HOTKEYF_ALT)
  122.         {
  123.             GetKeyName(VK_MENU, sz+lstrlen(sz), FALSE);
  124.             lstrcat(sz,szPlus);
  125.         }
  126.         GetKeyName(wVirtKey, sz+lstrlen(sz), wMods & HOTKEYF_EXT);
  127.     }
  128.     else
  129.         LocalizedLoadString(IDS_NONE,sz,100);
  130.     cch = lstrlen(sz);
  131.     HideCaret(hwnd);
  132.     InvalidateRect(hwnd, NULL, TRUE);
  133.     hdc = BeginPaint(hwnd,&ps);
  134.     hFont = SelectObject(hdc, (HFONT)GetWindowInt(hwnd,GWU_HFONT));
  135.     x = g_cxBorder;
  136.     y = g_cyBorder;
  137.     if (IsWindowEnabled(hwnd))
  138.     {
  139.         SetBkColor(hdc, g_clrWindow);
  140.         SetTextColor(hdc, g_clrWindowText);
  141.         TextOut(hdc,x,y,sz,cch);
  142.     }
  143.     else
  144.     {
  145.         // set the background color to Grayed like edit controls
  146.         SetBkColor(hdc, g_clrBtnFace);
  147.         if (g_clrGrayText)
  148.         {
  149.             SetTextColor(hdc,g_clrGrayText);
  150.             TextOut(hdc,x,y,sz,cch);
  151.         }
  152.         else
  153.         {
  154.             GrayString(hdc,NULL,NULL,(ULONG_PTR)(LPTSTR)sz,cch,x,y,0,0);
  155.         }
  156.     }
  157.     MGetTextExtent(hdc, sz, cch, &x, NULL);
  158.      if (GetFocus() == hwnd)
  159.          SetCaretPos(x+g_cxBorder,
  160.                     g_cyBorder);
  161.     ShowCaret(hwnd);
  162. #if 0
  163.     if (hFont)
  164.         SelectObject(hdc,hFont);
  165. #endif
  166.     EndPaint(hwnd,&ps);
  167. }
  168. void NEAR PASCAL HKMSetRules(HWND hwnd, WPARAM wParam, LPARAM lParam)
  169. {
  170.     SetWindowInt(hwnd, GWU_INVALID, wParam);
  171.     SetWindowInt(hwnd, GWU_DEFAULT, lParam);
  172. }
  173. HFONT NEAR PASCAL HKMSetFont(HWND hwnd, HFONT wParam)
  174. {
  175.     HFONT lParam;
  176.     HDC hdc;
  177.     INT cy;
  178.     lParam = (HFONT)GetWindowInt(hwnd,GWU_HFONT);
  179.     SetWindowInt(hwnd,GWU_HFONT,(LONG_PTR)wParam);
  180.     hdc = GetDC(hwnd);
  181.     if (wParam)
  182.         wParam = SelectObject(hdc, wParam);
  183.     MGetTextExtent(hdc, TEXT("C"), 1, NULL, &cy);
  184.     SetWindowInt(hwnd,GWU_YFONT,cy);
  185.     if (wParam)
  186.         SelectObject(hdc, wParam);
  187.     ReleaseDC(hwnd,hdc);
  188.     InvalidateRect(hwnd,NULL,TRUE);
  189.     return lParam;
  190. }
  191. LRESULT CALLBACK HotKeyWndProc(HWND hwnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
  192. {
  193.     WORD wVirtKey;
  194.     WORD wMods;
  195.     RECT rc;
  196.     HDC hdc;
  197.     switch (wMsg)
  198.     {
  199.     case WM_NCCREATE:
  200.         SetWindowBits(hwnd, GWL_EXSTYLE, WS_EX_CLIENTEDGE, WS_EX_CLIENTEDGE);
  201.         InitGlobalColors();
  202.         return TRUE;
  203.     case WM_CREATE:
  204.         SetHotKey(hwnd, 0, 0, FALSE);
  205.         HKMSetRules(hwnd, 0, 0);
  206.         HKMSetFont(hwnd, g_hfontSystem);
  207.         break;
  208.     case WM_SETFOCUS:
  209.         InvalidateRect(hwnd,NULL,TRUE);
  210.         CreateCaret(hwnd,NULL,0,(int)GetWindowInt(hwnd,GWU_YFONT));
  211.         ShowCaret(hwnd);
  212.         break;
  213.     case WM_KILLFOCUS:
  214.         if (!GetWindowInt(hwnd, GWU_VIRTKEY))
  215.         SetHotKey(hwnd, 0, 0, TRUE);
  216.         DestroyCaret();
  217.         break;
  218.     case WM_GETDLGCODE:
  219.         return DLGC_WANTCHARS | DLGC_WANTARROWS; // | DLGC_WANTALLKEYS;
  220.     case HKM_SETHOTKEY:
  221.         SetHotKey(hwnd, LOBYTE(wParam), HIBYTE(wParam), FALSE);
  222.         break;
  223.     case HKM_GETHOTKEY:
  224.         return (256*(BYTE)GetWindowInt(hwnd, GWU_MODS)) +
  225.                 ((BYTE)GetWindowInt(hwnd, GWU_VIRTKEY));
  226.         break;
  227.     case HKM_SETRULES:
  228.         HKMSetRules(hwnd, wParam, LOWORD(lParam));
  229.         break;
  230.     case WM_LBUTTONDOWN:
  231.         SetFocus(hwnd);
  232.         break;
  233.     case WM_SYSKEYDOWN:
  234.     case WM_KEYDOWN:
  235.         switch (wParam)
  236.         {
  237.         case VK_RETURN:
  238.         case VK_TAB:
  239.         case VK_SPACE:
  240.         case VK_DELETE:
  241.         case VK_ESCAPE:
  242.         case VK_BACK:
  243.         case VK_LWIN:
  244.         case VK_RWIN:
  245.         case VK_APPS:
  246.             SetHotKey(hwnd, 0, 0, TRUE);
  247.             return DefWindowProc(hwnd,wMsg,wParam,lParam);
  248.         case VK_MENU:
  249.         case VK_SHIFT:
  250.         case VK_CONTROL:
  251.             wVirtKey = 0;
  252.             goto SetNewHotKey;
  253.         default:
  254.             wVirtKey = (WORD) wParam;
  255. SetNewHotKey:
  256.             wMods = 0;
  257.             if (GetKeyState(VK_CONTROL) < 0)
  258.                 wMods |= HOTKEYF_CONTROL;
  259.             if (GetKeyState(VK_SHIFT) < 0)
  260.                 wMods |= HOTKEYF_SHIFT;
  261.             if (GetKeyState(VK_MENU) < 0)
  262.                 wMods |= HOTKEYF_ALT;
  263.             #define IsFUNKEY(vk) ((vk) >= VK_F1 && (vk) <= VK_F24)
  264.             #define IsNUMKEY(vk) ((vk) >= VK_NUMPAD0 && (vk) <= VK_DIVIDE)
  265.             //
  266.             //  dont enforce any rules on the Function keys or
  267.             //  on the number pad keys.
  268.             //
  269.             // if this combination is invalid, use the default
  270.             if (!IsFUNKEY(wVirtKey) &&
  271.                 !IsNUMKEY(wVirtKey) &&
  272.                 (s_Combos[wMods] & GetWindowInt(hwnd, GWU_INVALID)))
  273.             {
  274.                 wMods = (WORD)GetWindowInt(hwnd, GWU_DEFAULT);
  275.             }
  276.             if (lParam & F_EXT)
  277.                 wMods |= HOTKEYF_EXT;
  278.             SetHotKey(hwnd, wVirtKey, wMods, TRUE);
  279.             break;
  280.         }
  281.         break;
  282.     case WM_SYSKEYUP:
  283.     case WM_CHAR:
  284.     case WM_SYSCHAR:
  285.     case WM_KEYUP:
  286.         if (!GetWindowInt(hwnd, GWU_VIRTKEY))
  287.             SetHotKey(hwnd, 0, 0, TRUE);
  288.         break;
  289.     case WM_GETFONT:
  290.         return GetWindowInt(hwnd,GWU_HFONT);
  291.     case WM_SETFONT:
  292.         return (LRESULT)(UINT_PTR)HKMSetFont(hwnd, (HFONT)wParam);
  293.     case WM_PAINT:
  294.         PaintHotKey(hwnd);
  295.         break;
  296.     case WM_ERASEBKGND:
  297.         HideCaret(hwnd);
  298.         hdc = GetDC(hwnd);
  299.         GetClientRect(hwnd, &rc);
  300.         if (IsWindowEnabled(hwnd)) {
  301.             FillRect(hdc, &rc, g_hbrWindow);
  302.         } else {
  303.             FillRect(hdc, &rc, g_hbrBtnFace);
  304.         }
  305.         ReleaseDC(hwnd, hdc);
  306.         // lParam = DefWindowProc(hwnd,wMsg,wParam,lParam);
  307.         ShowCaret(hwnd);
  308.         return TRUE;
  309.     case WM_GETOBJECT:
  310.         if( lParam == OBJID_QUERYCLASSNAMEIDX )
  311.             return MSAA_CLASSNAMEIDX_HOTKEY;
  312.         goto DoDefault;
  313.     case WM_ENABLE:
  314.         InvalidateRect(hwnd, NULL, TRUE);
  315.         goto DoDefault;
  316.     default:
  317. DoDefault:
  318.         return DefWindowProc(hwnd,wMsg,wParam,lParam);
  319.     }
  320.     return 0L;
  321. }