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.

392 lines
8.9 KiB

  1. /*
  2. * hotkey.c
  3. *
  4. * Copyright (c) 1991, Microsoft Corporation
  5. *
  6. * DESCRIPTION
  7. *
  8. * This file is for support of program manager under NT Windows.
  9. * This file is/was ported from hotkey.c (program manager).
  10. *
  11. * MODIFICATION HISTORY
  12. * Initial Version: x/x/90 Author Unknown, since he didn't feel
  13. * like commenting the code...
  14. *
  15. * NT 32b Version: 1/18/91 Jeff Pack
  16. * Intitial port to begin.
  17. *
  18. *
  19. */
  20. #include "progman.h"
  21. #define HK_SHIFT 0x0100
  22. #define HK_CONTROL 0x0200
  23. #define HK_ALT 0x0400
  24. #define HK_EXT 0x0800
  25. #define F_EXT 0x01000000L
  26. TCHAR szHotKey[] = TEXT("pmhotkey");
  27. typedef struct HOTKEYWINDOWBYTES {
  28. UINT hotkey;
  29. int cyFont;
  30. HFONT hfont;
  31. } HOTKEYWINDOWBYTES;
  32. #define HWL_HOTKEY FIELD_OFFSET(HOTKEYWINDOWBYTES, hotkey)
  33. #define HWL_CYFONT FIELD_OFFSET(HOTKEYWINDOWBYTES, cyFont)
  34. #define HWLP_FONT FIELD_OFFSET(HOTKEYWINDOWBYTES, hfont)
  35. /*** SetHotKey --
  36. *
  37. *
  38. * void APIENTRY SetHotKey(HWND hwnd, WORD hk)
  39. *
  40. * ENTRY - HWND hWnd
  41. * WORD hk
  42. *
  43. * EXIT - void
  44. *
  45. * SYNOPSIS - ???
  46. *
  47. * WARNINGS -
  48. * EFFECTS -
  49. *
  50. */
  51. void APIENTRY SetHotKey(HWND hwnd, WPARAM hk)
  52. {
  53. /* don't invalidate if it's the same
  54. */
  55. if((LONG)hk == GetWindowLong(hwnd, HWL_HOTKEY)){
  56. return;
  57. }
  58. SetWindowLong(hwnd, HWL_HOTKEY, (LONG)hk);
  59. InvalidateRect(hwnd,NULL,TRUE);
  60. }
  61. /*** GetKeyName --
  62. *
  63. *
  64. * void APIENTRY GetKeyName(WORD vk, PSTR psz, BOOL fExt)
  65. *
  66. * ENTRY - WORD hk
  67. * PSTR psz
  68. * BOOL fExt
  69. *
  70. * EXIT - void
  71. *
  72. * SYNOPSIS - ???
  73. *
  74. * WARNINGS -
  75. * EFFECTS -
  76. *
  77. */
  78. void APIENTRY GetKeyName(UINT vk, LPTSTR psz, BOOL fExt)
  79. {
  80. LONG scan;
  81. scan = (LONG)MapVirtualKey(vk,0) << 16;
  82. if (fExt){
  83. scan |= F_EXT;
  84. }
  85. GetKeyNameText(scan,psz,50);
  86. }
  87. /*** PaintHotKey --
  88. *
  89. *
  90. * void APIENTRY PaintHotKey(register HWND hwnd)
  91. *
  92. * ENTRY - HWND hWnd
  93. *
  94. * EXIT - void
  95. *
  96. * SYNOPSIS - ???
  97. *
  98. * WARNINGS -
  99. * EFFECTS -
  100. *
  101. */
  102. void APIENTRY PaintHotKey(register HWND hwnd)
  103. {
  104. TCHAR sz[128];
  105. TCHAR szPlus[10];
  106. WORD cch;
  107. WORD hk;
  108. register HDC hdc;
  109. #ifndef ORGCODE
  110. SIZE size;
  111. #endif
  112. PAINTSTRUCT ps;
  113. int x, y;
  114. HANDLE hFont;
  115. DWORD dwColor;
  116. LoadString(hAppInstance, IDS_PLUS, szPlus, CharSizeOf(szPlus));
  117. if(hk = (WORD)GetWindowLong(hwnd, HWL_HOTKEY)){
  118. sz[0] = 0;
  119. cch = 0;
  120. if (hk & HK_CONTROL){
  121. GetKeyName(VK_CONTROL,sz,FALSE);
  122. lstrcat(sz,szPlus);
  123. }
  124. if (hk & HK_SHIFT){
  125. GetKeyName(VK_SHIFT, sz + lstrlen(sz), FALSE);
  126. lstrcat(sz,szPlus);
  127. }
  128. if (hk & HK_ALT){
  129. GetKeyName(VK_MENU, sz + lstrlen(sz), FALSE);
  130. lstrcat(sz,szPlus);
  131. }
  132. GetKeyName((UINT)LOBYTE(hk), sz + lstrlen(sz), hk & HK_EXT);
  133. }
  134. else{
  135. LoadString(hAppInstance,IDS_NONE,sz,100);
  136. }
  137. cch = (WORD)lstrlen(sz);
  138. HideCaret(hwnd);
  139. hdc = BeginPaint(hwnd,&ps);
  140. SetBkMode(hdc, TRANSPARENT);
  141. hFont = SelectObject(hdc,(HANDLE)GetWindowLongPtr(hwnd,HWLP_FONT));
  142. x = GetSystemMetrics(SM_CXBORDER);
  143. y = GetSystemMetrics(SM_CYBORDER);
  144. if (IsWindowEnabled(hwnd)){
  145. dwColor = GetSysColor(COLOR_WINDOWTEXT);
  146. dwColor = SetTextColor(hdc,dwColor);
  147. TextOut(hdc,x,y,sz,cch);
  148. }
  149. else if (dwColor = GetSysColor(COLOR_GRAYTEXT)){
  150. dwColor = SetTextColor(hdc,dwColor);
  151. TextOut(hdc,x,y,sz,cch);
  152. SetTextColor(hdc,dwColor);
  153. }
  154. else{
  155. GrayString(hdc,NULL,NULL,(LPARAM)(LPTSTR)sz,cch,x,y,0,0);
  156. }
  157. #ifdef ORGCODE
  158. x = (WORD)GetTextExtentPoint(hdc,sz,cch);
  159. #else
  160. /*Used to return x/y in DWORD, now returns cx,cy in size*/
  161. GetTextExtentPoint(hdc, sz, cch, &size);
  162. x = size.cx;
  163. #endif
  164. if (GetFocus() == hwnd)
  165. SetCaretPos(x+GetSystemMetrics(SM_CXBORDER), GetSystemMetrics(SM_CYBORDER));
  166. ShowCaret(hwnd);
  167. if (hFont){
  168. SelectObject(hdc,hFont);
  169. }
  170. SetBkMode(hdc, OPAQUE);
  171. EndPaint(hwnd,&ps);
  172. }
  173. /*** HotKeyWndProc --
  174. *
  175. *
  176. * LRESULT APIENTRY HotKeyWndProc(register HWND hwnd, UINT wMsg,
  177. * register WPARAM wParam, LPARAM lParam)
  178. *
  179. * ENTRY - HWND hWnd
  180. * WORD wMsg
  181. * WPARAM wParam
  182. * LPARAM lParam
  183. * EXIT - LRESULT xxx - returns info, or zero, for nothing to return
  184. *
  185. * SYNOPSIS - ???
  186. *
  187. * WARNINGS -
  188. * EFFECTS -
  189. *
  190. */
  191. LRESULT APIENTRY HotKeyWndProc(register HWND hwnd, UINT wMsg,
  192. register WPARAM wParam, LPARAM lParam)
  193. {
  194. HDC hdc;
  195. WORD wT;
  196. #ifndef ORGCODE
  197. SIZE size;
  198. #endif
  199. switch (wMsg){
  200. case WM_CREATE:
  201. SetHotKey(hwnd,0);
  202. SendMessage(hwnd,WM_SETFONT,(WPARAM)GetStockObject(SYSTEM_FONT),0L);
  203. break;
  204. case WM_SETFOCUS:
  205. InvalidateRect(hwnd,NULL,TRUE);
  206. CreateCaret(hwnd,NULL,0,GetWindowLong(hwnd,HWL_CYFONT));
  207. ShowCaret(hwnd);
  208. break;
  209. case WM_KILLFOCUS:
  210. if (!LOBYTE(GetWindowLong(hwnd,HWL_HOTKEY))){
  211. SetHotKey(hwnd,0);
  212. }
  213. DestroyCaret();
  214. break;
  215. case WM_GETDLGCODE:
  216. return DLGC_WANTCHARS | DLGC_WANTARROWS;
  217. case WM_SETTEXT:
  218. SetHotKey(hwnd,LOWORD(lParam));
  219. break;
  220. case WM_GETTEXT:
  221. *(LPINT)lParam = GetWindowLong(hwnd,HWL_HOTKEY);
  222. break;
  223. case WM_SETHOTKEY:
  224. SetHotKey(hwnd,(WPARAM) wParam);
  225. break;
  226. case WM_GETHOTKEY:
  227. return GetWindowLong(hwnd,HWL_HOTKEY);
  228. case WM_LBUTTONDOWN:
  229. SetFocus(hwnd);
  230. break;
  231. case WM_SYSKEYDOWN:
  232. case WM_KEYDOWN:
  233. switch (wParam) {
  234. case VK_RETURN:
  235. case VK_TAB:
  236. case VK_SPACE:
  237. case VK_DELETE:
  238. case VK_ESCAPE:
  239. case VK_BACK:
  240. SetHotKey(hwnd,0);
  241. return DefWindowProc(hwnd,wMsg,wParam,lParam);
  242. case VK_MENU:
  243. case VK_SHIFT:
  244. case VK_CONTROL:
  245. wParam = 0;
  246. /*** fall thru ***/
  247. default:
  248. if (GetKeyState(VK_CONTROL) < 0)
  249. wParam |= HK_CONTROL;
  250. if (GetKeyState(VK_SHIFT) < 0)
  251. wParam |= HK_SHIFT;
  252. if (GetKeyState(VK_MENU) < 0)
  253. wParam |= HK_ALT;
  254. if (lParam & F_EXT)
  255. wParam |= HK_EXT;
  256. // more than one shift key must be specified. That is,
  257. // CONTROL+ALT, CONTROL+SHIFT, SHIFT+ALT
  258. // get the bitmask of shift keys and then determine whether
  259. // it has at least two bits set via the bitcount trick
  260. // if not enough control things are present we add them
  261. // in. so the user gets the idea.
  262. if ((wParam & HK_ALT) && !(wParam & HK_CONTROL)
  263. && !(wParam & HK_SHIFT)) {
  264. break;
  265. }
  266. else {
  267. wT = (WORD)(wParam & (HK_CONTROL|HK_SHIFT|HK_ALT));
  268. if (!wT || !(wT & (wT - 1)))
  269. wParam |= HK_CONTROL | HK_ALT;
  270. SetHotKey(hwnd,wParam);
  271. break;
  272. }
  273. }
  274. break;
  275. case WM_SYSKEYUP:
  276. case WM_CHAR:
  277. case WM_SYSCHAR:
  278. case WM_KEYUP:
  279. if (!LOBYTE((WORD)GetWindowLong(hwnd,HWL_HOTKEY)))
  280. SetHotKey(hwnd,0);
  281. break;
  282. case WM_GETFONT:
  283. return GetWindowLongPtr(hwnd,HWLP_FONT);
  284. case WM_SETFONT:
  285. lParam = GetWindowLongPtr(hwnd,HWLP_FONT);
  286. SetWindowLongPtr(hwnd,HWLP_FONT,wParam);
  287. hdc = GetDC(hwnd);
  288. wParam = (WPARAM) SelectObject(hdc,(HANDLE)wParam);
  289. GetTextExtentPoint(hdc, TEXT("C"), 1, &size);
  290. SetWindowLong(hwnd, HWL_CYFONT, size.cy);
  291. if (wParam){
  292. SelectObject(hdc,(HANDLE)wParam);
  293. }
  294. ReleaseDC(hwnd,hdc);
  295. InvalidateRect(hwnd,NULL,TRUE);
  296. return lParam;
  297. case WM_PAINT:
  298. PaintHotKey(hwnd);
  299. break;
  300. case WM_ERASEBKGND:
  301. HideCaret(hwnd);
  302. lParam = DefWindowProc(hwnd,wMsg,wParam,lParam);
  303. ShowCaret(hwnd);
  304. return lParam;
  305. default:
  306. return DefWindowProc(hwnd,wMsg,wParam,lParam);
  307. }
  308. return 0L;
  309. }
  310. /*** RegisterHotKeyClass --
  311. *
  312. *
  313. * BOOL APIENTRY RegisterHotKeyClass(HANDLE hInstance)
  314. *
  315. * ENTRY - HWND HANDLE hInstance
  316. * EXIT - BOOL xxx - returns return code from RegisterClass
  317. *
  318. * SYNOPSIS - ???
  319. *
  320. * WARNINGS - This (under 16) took hInstance. Under win32, hInstance is
  321. * NULL, cause there is only one instance.
  322. * EFFECTS -
  323. *
  324. */
  325. BOOL APIENTRY RegisterHotKeyClass(HANDLE hInstance)
  326. {
  327. WNDCLASS wc;
  328. wc.style = 0;
  329. wc.lpfnWndProc = HotKeyWndProc;
  330. wc.cbClsExtra = 0;
  331. wc.cbWndExtra = sizeof(HOTKEYWINDOWBYTES);
  332. wc.hInstance = hInstance;
  333. wc.hIcon = NULL;
  334. wc.hCursor = NULL;
  335. wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  336. wc.lpszMenuName = NULL;
  337. wc.lpszClassName = szHotKey;
  338. return RegisterClass(&wc);
  339. }