Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

365 lines
9.3 KiB

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