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.

480 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. // timer ID
  34. #define BLINK 1000
  35. // Note that 1300 is converted to -1, which means "off". The max value
  36. // that we set is actually 1200.
  37. #define CURSORMIN 200
  38. #define CURSORMAX 1300
  39. #define CURSORRANGE (CURSORMAX - CURSORMIN)
  40. static ARROWVSCROLL avsDelay = { -1,
  41. 1,
  42. -KDELAY_RANGE / 4,
  43. KDELAY_RANGE / 4,
  44. KDELAY_MAX,
  45. KDELAY_MIN
  46. };
  47. static ARROWVSCROLL avsSpeed = { -1,
  48. 1,
  49. -KSPEED_RANGE / 4,
  50. KSPEED_RANGE / 4,
  51. KSPEED_MAX,
  52. KSPEED_MIN
  53. };
  54. static ARROWVSCROLL avsCursor = { -1, // lineup
  55. 1, // linedown
  56. -CURSORRANGE / 400, // pageup
  57. CURSORRANGE / 400, // pagedown
  58. CURSORRANGE / 100, // top
  59. 0, // bottom
  60. 0, // thumbpos
  61. 0 // thumbtrack
  62. };
  63. //
  64. // Context Help Ids.
  65. //
  66. static DWORD aKbdHelpIds[] =
  67. {
  68. KDELAY_GROUP, IDH_COMM_GROUPBOX,
  69. KBLINK_GROUP, IDH_COMM_GROUPBOX,
  70. KDELAY_SCROLL, IDH_DLGKEY_REPDEL,
  71. KSPEED_SCROLL, IDH_DLGKEY_REPSPEED,
  72. KREPEAT_EDIT, IDH_DLGKEY_REPTEST,
  73. KBLINK_EDIT, IDH_DLGKEY_CURSOR_GRAPHIC,
  74. KCURSOR_BLINK, IDH_DLGKEY_CURSOR_GRAPHIC,
  75. KCURSOR_SCROLL, IDH_DLGKEY_CURSBLNK,
  76. 0, 0
  77. };
  78. //
  79. // Global Variables.
  80. //
  81. //
  82. // FEATURE - these should be moved into the KeyboardSpdStr structure
  83. //
  84. static UINT uOriginalDelay, uOriginalSpeed;
  85. static UINT uBlinkTime;
  86. static UINT uNewBlinkTime;
  87. static BOOL bKbNeedsReset = FALSE;
  88. static HWND hwndCursorScroll;
  89. static HWND hwndCursorBlink;
  90. static BOOL fBlink = TRUE;
  91. //
  92. // Typedef Declarations.
  93. //
  94. typedef struct tag_KeyboardSpdStr
  95. {
  96. HWND hDlg; // HWND hKeyboardSpdDlg;
  97. } KEYBOARDSPDSTR, *PKEYBOARDSPDSTR;
  98. //
  99. // Helper functions to handle the caret "off" setting
  100. //
  101. void _SetCaretBlinkTime(UINT uInterval)
  102. {
  103. if (uInterval != uNewBlinkTime)
  104. {
  105. uNewBlinkTime = uInterval;
  106. if (CURSORMAX == uInterval)
  107. uInterval = (UINT)-1; // blink is "off"
  108. SetCaretBlinkTime(uInterval);
  109. }
  110. }
  111. void _SetTimer(HWND hDlg, UINT uInterval)
  112. {
  113. if (uInterval < CURSORMAX)
  114. {
  115. SetTimer(hDlg, BLINK, uInterval, NULL);
  116. }
  117. else
  118. {
  119. // Caret blink is "off".
  120. // Kill the timer and show our pseudo-caret.
  121. KillTimer(hDlg, BLINK);
  122. fBlink = TRUE;
  123. ShowWindow(hwndCursorBlink, SW_SHOW);
  124. }
  125. }
  126. ////////////////////////////////////////////////////////////////////////////
  127. //
  128. // KeyboardSpeedSupported
  129. //
  130. ////////////////////////////////////////////////////////////////////////////
  131. BOOL KeyboardSpeedSupported()
  132. {
  133. #ifdef WINNT
  134. //
  135. // FEATURE For Windows NT we assume that all keyboards can
  136. // handle the SetSpeed - we might be able to do a
  137. // better check in the future if KEYBOARD.DLL is available.
  138. //
  139. return (TRUE);
  140. #else
  141. HANDLE hKeyboardModule = LoadLibrary16(TEXT("KEYBOARD"));
  142. BOOL bCanDorkWithTheSpeed = FALSE;
  143. if (hKeyboardModule)
  144. {
  145. if (GetProcAddress16(hKeyboardModule, TEXT("SetSpeed")))
  146. {
  147. bCanDorkWithTheSpeed = TRUE;
  148. }
  149. FreeLibrary16(hKeyboardModule);
  150. }
  151. return (bCanDorkWithTheSpeed);
  152. #endif
  153. }
  154. ////////////////////////////////////////////////////////////////////////////
  155. //
  156. // SetDelayAndSpeed
  157. //
  158. ////////////////////////////////////////////////////////////////////////////
  159. void SetDelayAndSpeed(
  160. HWND hDlg,
  161. int nDelay,
  162. int nSpeed,
  163. UINT uFlags)
  164. {
  165. if (nDelay < 0)
  166. {
  167. nDelay = (int)SendDlgItemMessage( hDlg,
  168. KDELAY_SCROLL,
  169. TBM_GETPOS,
  170. 0,
  171. 0L );
  172. }
  173. if (nSpeed < 0)
  174. {
  175. nSpeed = (int)SendDlgItemMessage( hDlg,
  176. KSPEED_SCROLL,
  177. TBM_GETPOS,
  178. 0,
  179. 0L );
  180. }
  181. //
  182. // Only send the WININICHANGE once.
  183. //
  184. SystemParametersInfo( SPI_SETKEYBOARDSPEED,
  185. nSpeed,
  186. 0,
  187. uFlags & ~SPIF_SENDWININICHANGE );
  188. SystemParametersInfo( SPI_SETKEYBOARDDELAY,
  189. KDELAY_MAX - nDelay + KDELAY_MIN,
  190. 0L,
  191. uFlags );
  192. }
  193. ////////////////////////////////////////////////////////////////////////////
  194. //
  195. // DestroyKeyboardSpdDlg
  196. //
  197. ////////////////////////////////////////////////////////////////////////////
  198. void DestroyKeyboardSpdDlg(
  199. PKEYBOARDSPDSTR pKstr)
  200. {
  201. HWND hDlg;
  202. if (pKstr)
  203. {
  204. hDlg = pKstr->hDlg;
  205. LocalFree((HGLOBAL)pKstr);
  206. SetWindowLongPtr(hDlg, DWLP_USER, 0);
  207. }
  208. }
  209. ////////////////////////////////////////////////////////////////////////////
  210. //
  211. // GetSpeedGlobals
  212. //
  213. // Get Repeat Speed, Delay, and Blink Time.
  214. //
  215. ////////////////////////////////////////////////////////////////////////////
  216. VOID GetSpeedGlobals()
  217. {
  218. SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, &uOriginalSpeed, FALSE);
  219. SystemParametersInfo(SPI_GETKEYBOARDDELAY, 0, &uOriginalDelay, FALSE);
  220. uOriginalDelay = KDELAY_MAX - uOriginalDelay + KDELAY_MIN;
  221. // -1 means "off"
  222. uBlinkTime = GetCaretBlinkTime();
  223. if ((UINT)-1 == uBlinkTime || uBlinkTime > CURSORMAX)
  224. uBlinkTime = CURSORMAX;
  225. uNewBlinkTime = uBlinkTime;
  226. }
  227. ////////////////////////////////////////////////////////////////////////////
  228. //
  229. // InitKeyboardSpdDlg
  230. //
  231. ////////////////////////////////////////////////////////////////////////////
  232. BOOL InitKeyboardSpdDlg(
  233. HWND hDlg)
  234. {
  235. HourGlass(TRUE);
  236. if (!KeyboardSpeedSupported())
  237. {
  238. MyMessageBox( hDlg,
  239. IDS_KEYBD_NOSETSPEED,
  240. IDS_KEYBD_TITLE,
  241. MB_OK | MB_ICONINFORMATION );
  242. HourGlass(FALSE);
  243. return (FALSE);
  244. }
  245. //
  246. // Get Repeat Speed, Delay, and Blink Time.
  247. //
  248. GetSpeedGlobals();
  249. TrackInit(GetDlgItem(hDlg, KSPEED_SCROLL), uOriginalSpeed, &avsSpeed);
  250. TrackInit(GetDlgItem(hDlg, KDELAY_SCROLL), uOriginalDelay, &avsDelay);
  251. TrackInit(GetDlgItem(hDlg, KCURSOR_SCROLL), (CURSORMAX - uBlinkTime) / 100, &avsCursor );
  252. hwndCursorScroll = GetDlgItem(hDlg, KCURSOR_SCROLL);
  253. hwndCursorBlink = GetDlgItem(hDlg, KCURSOR_BLINK);
  254. _SetTimer(hDlg, uBlinkTime);
  255. HourGlass(FALSE);
  256. return (TRUE);
  257. }
  258. ////////////////////////////////////////////////////////////////////////////
  259. //
  260. // KeyboardSpdDlg
  261. //
  262. ////////////////////////////////////////////////////////////////////////////
  263. static const TCHAR c_szUserDesktopKey[] = REGSTR_PATH_DESKTOP;
  264. static const TCHAR c_szCursorBlink[] = TEXT("CursorBlinkRate");
  265. INT_PTR CALLBACK KeyboardSpdDlg(
  266. HWND hDlg,
  267. UINT message,
  268. WPARAM wParam,
  269. LPARAM lParam)
  270. {
  271. PKEYBOARDSPDSTR pKstr = (PKEYBOARDSPDSTR)GetWindowLongPtr(hDlg, DWLP_USER);
  272. switch (message)
  273. {
  274. case ( WM_INITDIALOG ) :
  275. {
  276. bKbNeedsReset = FALSE;
  277. return (InitKeyboardSpdDlg(hDlg));
  278. break;
  279. }
  280. case ( WM_DESTROY ) :
  281. {
  282. DestroyKeyboardSpdDlg(pKstr);
  283. break;
  284. }
  285. case ( WM_HSCROLL ) :
  286. {
  287. if ((HWND)lParam == hwndCursorScroll)
  288. {
  289. int nCurrent = (int)SendMessage( (HWND)lParam,
  290. TBM_GETPOS,
  291. 0,
  292. 0L );
  293. _SetCaretBlinkTime(CURSORMAX - (nCurrent * 100));
  294. _SetTimer(hDlg, uNewBlinkTime);
  295. }
  296. else
  297. {
  298. SetDelayAndSpeed(hDlg, -1, -1, 0);
  299. bKbNeedsReset = TRUE;
  300. }
  301. SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0L);
  302. break;
  303. }
  304. case ( WM_TIMER ) :
  305. {
  306. if (wParam == BLINK)
  307. {
  308. fBlink = !fBlink;
  309. ShowWindow(hwndCursorBlink, fBlink ? SW_SHOW : SW_HIDE);
  310. }
  311. break;
  312. }
  313. case ( WM_WININICHANGE ) :
  314. case ( WM_SYSCOLORCHANGE ) :
  315. case ( WM_DISPLAYCHANGE ) :
  316. {
  317. SHPropagateMessage(hDlg, message, wParam, lParam, TRUE);
  318. break;
  319. }
  320. case ( WM_HELP ) : // F1
  321. {
  322. WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle,
  323. NULL,
  324. HELP_WM_HELP,
  325. (DWORD_PTR)(LPTSTR)aKbdHelpIds );
  326. break;
  327. }
  328. case ( WM_CONTEXTMENU ) : // right mouse click
  329. {
  330. WinHelp( (HWND)wParam,
  331. NULL,
  332. HELP_CONTEXTMENU,
  333. (DWORD_PTR)(LPTSTR)aKbdHelpIds );
  334. break;
  335. }
  336. case ( WM_NOTIFY ) :
  337. {
  338. switch (((NMHDR *)lParam)->code)
  339. {
  340. case ( PSN_APPLY ) :
  341. {
  342. HKEY hk;
  343. HourGlass(TRUE);
  344. if (RegCreateKey( HKEY_CURRENT_USER,
  345. c_szUserDesktopKey,
  346. &hk ) == ERROR_SUCCESS)
  347. {
  348. TCHAR buf[16];
  349. if (CURSORMAX == uNewBlinkTime)
  350. lstrcpy(buf, TEXT("-1"));
  351. else
  352. wsprintf(buf, TEXT("%d"), uNewBlinkTime);
  353. RegSetValueEx( hk,
  354. c_szCursorBlink,
  355. 0,
  356. REG_SZ,
  357. (LPBYTE)buf,
  358. (DWORD)(lstrlen(buf) + 1) * sizeof(TCHAR) );
  359. RegCloseKey(hk);
  360. }
  361. SetDelayAndSpeed( hDlg,
  362. -1,
  363. -1,
  364. SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE );
  365. GetSpeedGlobals();
  366. HourGlass(FALSE);
  367. break;
  368. }
  369. case ( PSN_RESET ) :
  370. {
  371. _SetCaretBlinkTime(uBlinkTime);
  372. if (bKbNeedsReset)
  373. {
  374. //
  375. // Restore the original keyboard speed.
  376. //
  377. SetDelayAndSpeed( hDlg,
  378. uOriginalDelay,
  379. uOriginalSpeed,
  380. 0 );
  381. }
  382. break;
  383. }
  384. }
  385. break;
  386. }
  387. default :
  388. {
  389. return FALSE;
  390. }
  391. }
  392. return (TRUE);
  393. }