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.

458 lines
12 KiB

  1. /*++
  2. Copyright (c) 1994-1998, Microsoft Corporation All rights reserved.
  3. Module Name:
  4. keybdspd.c
  5. Abstract:
  6. This module contains the main routines for the Keyboard applet's
  7. Speed property page.
  8. Revision History:
  9. --*/
  10. //
  11. // Include Files.
  12. //
  13. #include "main.h"
  14. #include "rc.h"
  15. #include "util.h"
  16. #include <regstr.h>
  17. #include <help.h>
  18. //
  19. // Constant Declarations.
  20. //
  21. #define KSPEED_MIN 0
  22. #define KSPEED_MAX 31
  23. #define KSPEED_RANGE (KSPEED_MAX - KSPEED_MIN + 1)
  24. //
  25. // For keyboard delay control.
  26. //
  27. #define KDELAY_MIN 0
  28. #define KDELAY_MAX 3
  29. #define KDELAY_RANGE (KDELAY_MAX - KDELAY_MIN + 1)
  30. //
  31. // For control of the cursor blink rate.
  32. //
  33. #define BLINK 1000
  34. #define CURSORMIN 200
  35. #define CURSORMAX 1200
  36. #define CURSORSUM (CURSORMIN + CURSORMAX)
  37. #define CURSORRANGE (CURSORMAX - CURSORMIN)
  38. static ARROWVSCROLL avsDelay = { -1,
  39. 1,
  40. -KDELAY_RANGE / 4,
  41. KDELAY_RANGE / 4,
  42. KDELAY_MAX,
  43. KDELAY_MIN
  44. };
  45. static ARROWVSCROLL avsSpeed = { -1,
  46. 1,
  47. -KSPEED_RANGE / 4,
  48. KSPEED_RANGE / 4,
  49. KSPEED_MAX,
  50. KSPEED_MIN
  51. };
  52. static ARROWVSCROLL avsCursor = { -1,
  53. 1,
  54. -CURSORRANGE / 400,
  55. CURSORRANGE / 400,
  56. CURSORMAX / 100,
  57. CURSORMIN / 100,
  58. 0,
  59. 0
  60. };
  61. //
  62. // Context Help Ids.
  63. //
  64. static DWORD aKbdHelpIds[] =
  65. {
  66. KDELAY_GROUP, IDH_COMM_GROUPBOX,
  67. KBLINK_GROUP, IDH_COMM_GROUPBOX,
  68. KDELAY_SCROLL, IDH_DLGKEY_REPDEL,
  69. KSPEED_SCROLL, IDH_DLGKEY_REPSPEED,
  70. KREPEAT_EDIT, IDH_DLGKEY_REPTEST,
  71. KBLINK_EDIT, IDH_DLGKEY_CURSOR_GRAPHIC,
  72. KCURSOR_BLINK, IDH_DLGKEY_CURSBLNK,
  73. KCURSOR_SCROLL, IDH_DLGKEY_CURSBLNK,
  74. 0, 0
  75. };
  76. //
  77. // Global Variables.
  78. //
  79. //
  80. // FEATURE - these should be moved into the KeyboardSpdStr structure
  81. //
  82. static UINT uOriginalDelay, uOriginalSpeed;
  83. static UINT uBlinkTime;
  84. static UINT uNewBlinkTime;
  85. static BOOL bKbNeedsReset = FALSE;
  86. static HWND hwndCursorScroll;
  87. static RECT rCursor;
  88. //
  89. // Typedef Declarations.
  90. //
  91. typedef struct tag_KeyboardSpdStr
  92. {
  93. HWND hDlg; // HWND hKeyboardSpdDlg;
  94. } KEYBOARDSPDSTR, *PKEYBOARDSPDSTR;
  95. ////////////////////////////////////////////////////////////////////////////
  96. //
  97. // KeyboardSpeedSupported
  98. //
  99. ////////////////////////////////////////////////////////////////////////////
  100. BOOL KeyboardSpeedSupported()
  101. {
  102. #ifdef WINNT
  103. //
  104. // FEATURE For Windows NT we assume that all keyboards can
  105. // handle the SetSpeed - we might be able to do a
  106. // better check in the future if KEYBOARD.DLL is available.
  107. //
  108. return (TRUE);
  109. #else
  110. HANDLE hKeyboardModule = LoadLibrary16(TEXT("KEYBOARD"));
  111. BOOL bCanDorkWithTheSpeed = FALSE;
  112. if (hKeyboardModule)
  113. {
  114. if (GetProcAddress16(hKeyboardModule, TEXT("SetSpeed")))
  115. {
  116. bCanDorkWithTheSpeed = TRUE;
  117. }
  118. FreeLibrary16(hKeyboardModule);
  119. }
  120. return (bCanDorkWithTheSpeed);
  121. #endif
  122. }
  123. ////////////////////////////////////////////////////////////////////////////
  124. //
  125. // SetDelayAndSpeed
  126. //
  127. ////////////////////////////////////////////////////////////////////////////
  128. void SetDelayAndSpeed(
  129. HWND hDlg,
  130. int nDelay,
  131. int nSpeed,
  132. UINT uFlags)
  133. {
  134. if (nDelay < 0)
  135. {
  136. nDelay = (int)SendDlgItemMessage( hDlg,
  137. KDELAY_SCROLL,
  138. TBM_GETPOS,
  139. 0,
  140. 0L );
  141. }
  142. if (nSpeed < 0)
  143. {
  144. nSpeed = (int)SendDlgItemMessage( hDlg,
  145. KSPEED_SCROLL,
  146. TBM_GETPOS,
  147. 0,
  148. 0L );
  149. }
  150. //
  151. // Only send the WININICHANGE once.
  152. //
  153. SystemParametersInfo( SPI_SETKEYBOARDSPEED,
  154. nSpeed,
  155. 0,
  156. uFlags & ~SPIF_SENDWININICHANGE );
  157. SystemParametersInfo( SPI_SETKEYBOARDDELAY,
  158. KDELAY_MAX - nDelay + KDELAY_MIN,
  159. 0L,
  160. uFlags );
  161. }
  162. ////////////////////////////////////////////////////////////////////////////
  163. //
  164. // DestroyKeyboardSpdDlg
  165. //
  166. ////////////////////////////////////////////////////////////////////////////
  167. void DestroyKeyboardSpdDlg(
  168. PKEYBOARDSPDSTR pKstr)
  169. {
  170. HWND hDlg;
  171. if (pKstr)
  172. {
  173. hDlg = pKstr->hDlg;
  174. LocalFree((HGLOBAL)pKstr);
  175. SetWindowLongPtr(hDlg, DWLP_USER, 0);
  176. }
  177. }
  178. ////////////////////////////////////////////////////////////////////////////
  179. //
  180. // GetSpeedGlobals
  181. //
  182. // Get Repeat Speed, Delay, and Blink Time.
  183. //
  184. ////////////////////////////////////////////////////////////////////////////
  185. VOID GetSpeedGlobals()
  186. {
  187. SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, &uOriginalSpeed, FALSE);
  188. SystemParametersInfo(SPI_GETKEYBOARDDELAY, 0, &uOriginalDelay, FALSE);
  189. uOriginalDelay = KDELAY_MAX - uOriginalDelay + KDELAY_MIN;
  190. uBlinkTime = uNewBlinkTime = GetCaretBlinkTime();
  191. }
  192. ////////////////////////////////////////////////////////////////////////////
  193. //
  194. // InitKeyboardSpdDlg
  195. //
  196. ////////////////////////////////////////////////////////////////////////////
  197. BOOL InitKeyboardSpdDlg(
  198. HWND hDlg)
  199. {
  200. HourGlass(TRUE);
  201. if (!KeyboardSpeedSupported())
  202. {
  203. MyMessageBox( hDlg,
  204. IDS_KEYBD_NOSETSPEED,
  205. IDS_KEYBD_TITLE,
  206. MB_OK | MB_ICONINFORMATION );
  207. HourGlass(FALSE);
  208. return (FALSE);
  209. }
  210. //
  211. // Get Repeat Speed, Delay, and Blink Time.
  212. //
  213. GetSpeedGlobals();
  214. TrackInit(GetDlgItem(hDlg, KSPEED_SCROLL), uOriginalSpeed, &avsSpeed);
  215. TrackInit(GetDlgItem(hDlg, KDELAY_SCROLL), uOriginalDelay, &avsDelay);
  216. TrackInit(GetDlgItem(hDlg, KCURSOR_SCROLL), (CURSORSUM - uBlinkTime) / 100, &avsCursor );
  217. hwndCursorScroll = GetDlgItem(hDlg, KCURSOR_SCROLL);
  218. GetWindowRect(GetDlgItem(hDlg, KCURSOR_BLINK), &rCursor);
  219. ScreenToClient(hDlg, (LPPOINT)&rCursor.left);
  220. ScreenToClient(hDlg, (LPPOINT)&rCursor.right);
  221. SetTimer(hDlg, BLINK, uBlinkTime, NULL);
  222. HourGlass(FALSE);
  223. return (TRUE);
  224. }
  225. ////////////////////////////////////////////////////////////////////////////
  226. //
  227. // KeyboardSpdDlg
  228. //
  229. ////////////////////////////////////////////////////////////////////////////
  230. static const TCHAR c_szUserDesktopKey[] = REGSTR_PATH_DESKTOP;
  231. static const TCHAR c_szCursorBlink[] = TEXT("CursorBlinkRate");
  232. INT_PTR CALLBACK KeyboardSpdDlg(
  233. HWND hDlg,
  234. UINT message,
  235. WPARAM wParam,
  236. LPARAM lParam)
  237. {
  238. PKEYBOARDSPDSTR pKstr = (PKEYBOARDSPDSTR)GetWindowLongPtr(hDlg, DWLP_USER);
  239. static BOOL fBlink = FALSE;
  240. switch (message)
  241. {
  242. case ( WM_INITDIALOG ) :
  243. {
  244. bKbNeedsReset = FALSE;
  245. return (InitKeyboardSpdDlg(hDlg));
  246. break;
  247. }
  248. case ( WM_DESTROY ) :
  249. {
  250. DestroyKeyboardSpdDlg(pKstr);
  251. break;
  252. }
  253. case ( WM_HSCROLL ) :
  254. {
  255. if ((HWND)lParam == hwndCursorScroll)
  256. {
  257. int nCurrent = (int)SendMessage( (HWND)lParam,
  258. TBM_GETPOS,
  259. 0,
  260. 0L );
  261. uNewBlinkTime = CURSORSUM - (nCurrent * 100);
  262. SetCaretBlinkTime(uNewBlinkTime);
  263. KillTimer(hDlg, BLINK);
  264. SetTimer(hDlg, BLINK, CURSORSUM - (nCurrent * 100), NULL);
  265. }
  266. else
  267. {
  268. SetDelayAndSpeed(hDlg, -1, -1, 0);
  269. bKbNeedsReset = TRUE;
  270. }
  271. SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0L);
  272. break;
  273. }
  274. case ( WM_TIMER ) :
  275. {
  276. if (wParam == BLINK)
  277. {
  278. HDC hDC = GetDC(hDlg);
  279. if (fBlink)
  280. {
  281. HBRUSH hBrush = CreateSolidBrush((COLORREF)0);
  282. FillRect(hDC, &rCursor, hBrush);
  283. DeleteObject(hBrush);
  284. }
  285. else
  286. InvalidateRect(hDlg, &rCursor, TRUE);
  287. fBlink = !fBlink;
  288. ReleaseDC(hDlg,hDC);
  289. }
  290. break;
  291. }
  292. case ( WM_WININICHANGE ) :
  293. case ( WM_SYSCOLORCHANGE ) :
  294. case ( WM_DISPLAYCHANGE ) :
  295. {
  296. SHPropagateMessage(hDlg, message, wParam, lParam, TRUE);
  297. break;
  298. }
  299. case ( WM_HELP ) : // F1
  300. {
  301. WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle,
  302. NULL,
  303. HELP_WM_HELP,
  304. (DWORD_PTR)(LPTSTR)aKbdHelpIds );
  305. break;
  306. }
  307. case ( WM_CONTEXTMENU ) : // right mouse click
  308. {
  309. WinHelp( (HWND)wParam,
  310. NULL,
  311. HELP_CONTEXTMENU,
  312. (DWORD_PTR)(LPTSTR)aKbdHelpIds );
  313. break;
  314. }
  315. case ( WM_NOTIFY ) :
  316. {
  317. switch (((NMHDR *)lParam)->code)
  318. {
  319. case ( PSN_APPLY ) :
  320. {
  321. HKEY hk;
  322. HourGlass(TRUE);
  323. if (RegCreateKey( HKEY_CURRENT_USER,
  324. c_szUserDesktopKey,
  325. &hk ) == ERROR_SUCCESS)
  326. {
  327. TCHAR buf[16];
  328. wsprintf(buf, TEXT("%d"), uNewBlinkTime);
  329. RegSetValueEx( hk,
  330. c_szCursorBlink,
  331. 0,
  332. REG_SZ,
  333. (LPBYTE)buf,
  334. (DWORD)(lstrlen(buf) + 1) * sizeof(TCHAR) );
  335. RegCloseKey(hk);
  336. }
  337. SetDelayAndSpeed( hDlg,
  338. -1,
  339. -1,
  340. SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE );
  341. GetSpeedGlobals();
  342. HourGlass(FALSE);
  343. break;
  344. }
  345. case ( PSN_RESET ) :
  346. {
  347. SetCaretBlinkTime(uBlinkTime);
  348. if (bKbNeedsReset)
  349. {
  350. //
  351. // Restore the original keyboard speed.
  352. //
  353. SetDelayAndSpeed( hDlg,
  354. uOriginalDelay,
  355. uOriginalSpeed,
  356. 0 );
  357. }
  358. break;
  359. }
  360. }
  361. break;
  362. }
  363. default :
  364. {
  365. return FALSE;
  366. }
  367. }
  368. return (TRUE);
  369. }