Source code of Windows XP (NT5)
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.

385 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. #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. CCCreateWindow();
  202. InitGlobalColors();
  203. return TRUE;
  204. case WM_DESTROY:
  205. CCDestroyWindow();
  206. break;
  207. case WM_CREATE:
  208. SetHotKey(hwnd, 0, 0, FALSE);
  209. HKMSetRules(hwnd, 0, 0);
  210. HKMSetFont(hwnd, g_hfontSystem);
  211. break;
  212. case WM_SETFOCUS:
  213. InvalidateRect(hwnd,NULL,TRUE);
  214. CreateCaret(hwnd,NULL,0,(int)GetWindowInt(hwnd,GWU_YFONT));
  215. ShowCaret(hwnd);
  216. break;
  217. case WM_KILLFOCUS:
  218. if (!GetWindowInt(hwnd, GWU_VIRTKEY))
  219. SetHotKey(hwnd, 0, 0, TRUE);
  220. DestroyCaret();
  221. break;
  222. case WM_GETDLGCODE:
  223. return DLGC_WANTCHARS | DLGC_WANTARROWS; // | DLGC_WANTALLKEYS;
  224. case HKM_SETHOTKEY:
  225. SetHotKey(hwnd, LOBYTE(wParam), HIBYTE(wParam), FALSE);
  226. break;
  227. case HKM_GETHOTKEY:
  228. return (256*(BYTE)GetWindowInt(hwnd, GWU_MODS)) +
  229. ((BYTE)GetWindowInt(hwnd, GWU_VIRTKEY));
  230. break;
  231. case HKM_SETRULES:
  232. HKMSetRules(hwnd, wParam, LOWORD(lParam));
  233. break;
  234. case WM_LBUTTONDOWN:
  235. SetFocus(hwnd);
  236. break;
  237. case WM_SYSKEYDOWN:
  238. case WM_KEYDOWN:
  239. switch (wParam)
  240. {
  241. case VK_RETURN:
  242. case VK_TAB:
  243. case VK_SPACE:
  244. case VK_DELETE:
  245. case VK_ESCAPE:
  246. case VK_BACK:
  247. case VK_LWIN:
  248. case VK_RWIN:
  249. case VK_APPS:
  250. SetHotKey(hwnd, 0, 0, TRUE);
  251. return DefWindowProc(hwnd,wMsg,wParam,lParam);
  252. case VK_MENU:
  253. case VK_SHIFT:
  254. case VK_CONTROL:
  255. wVirtKey = 0;
  256. goto SetNewHotKey;
  257. default:
  258. wVirtKey = (WORD) wParam;
  259. SetNewHotKey:
  260. wMods = 0;
  261. if (GetKeyState(VK_CONTROL) < 0)
  262. wMods |= HOTKEYF_CONTROL;
  263. if (GetKeyState(VK_SHIFT) < 0)
  264. wMods |= HOTKEYF_SHIFT;
  265. if (GetKeyState(VK_MENU) < 0)
  266. wMods |= HOTKEYF_ALT;
  267. #define IsFUNKEY(vk) ((vk) >= VK_F1 && (vk) <= VK_F24)
  268. #define IsNUMKEY(vk) ((vk) >= VK_NUMPAD0 && (vk) <= VK_DIVIDE)
  269. //
  270. // dont enforce any rules on the Function keys or
  271. // on the number pad keys.
  272. //
  273. // if this combination is invalid, use the default
  274. if (!IsFUNKEY(wVirtKey) &&
  275. !IsNUMKEY(wVirtKey) &&
  276. (s_Combos[wMods] & GetWindowInt(hwnd, GWU_INVALID)))
  277. {
  278. wMods = (WORD)GetWindowInt(hwnd, GWU_DEFAULT);
  279. }
  280. if (lParam & F_EXT)
  281. wMods |= HOTKEYF_EXT;
  282. SetHotKey(hwnd, wVirtKey, wMods, TRUE);
  283. break;
  284. }
  285. break;
  286. case WM_SYSKEYUP:
  287. case WM_CHAR:
  288. case WM_SYSCHAR:
  289. case WM_KEYUP:
  290. if (!GetWindowInt(hwnd, GWU_VIRTKEY))
  291. SetHotKey(hwnd, 0, 0, TRUE);
  292. break;
  293. case WM_GETFONT:
  294. return GetWindowInt(hwnd,GWU_HFONT);
  295. case WM_SETFONT:
  296. return (LRESULT)(UINT_PTR)HKMSetFont(hwnd, (HFONT)wParam);
  297. case WM_PAINT:
  298. PaintHotKey(hwnd);
  299. break;
  300. case WM_ERASEBKGND:
  301. HideCaret(hwnd);
  302. hdc = GetDC(hwnd);
  303. GetClientRect(hwnd, &rc);
  304. if (IsWindowEnabled(hwnd)) {
  305. FillRect(hdc, &rc, g_hbrWindow);
  306. } else {
  307. FillRect(hdc, &rc, g_hbrBtnFace);
  308. }
  309. ReleaseDC(hwnd, hdc);
  310. // lParam = DefWindowProc(hwnd,wMsg,wParam,lParam);
  311. ShowCaret(hwnd);
  312. return TRUE;
  313. case WM_GETOBJECT:
  314. if( lParam == OBJID_QUERYCLASSNAMEIDX )
  315. return MSAA_CLASSNAMEIDX_HOTKEY;
  316. goto DoDefault;
  317. case WM_ENABLE:
  318. InvalidateRect(hwnd, NULL, TRUE);
  319. goto DoDefault;
  320. default:
  321. DoDefault:
  322. return DefWindowProc(hwnd,wMsg,wParam,lParam);
  323. }
  324. return 0L;
  325. }