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.

825 lines
28 KiB

  1. // **************************************************************************
  2. // Filterkeys dialogs
  3. // Process the filterkeys dialogs
  4. // **************************************************************************
  5. #include "Access.h"
  6. extern DWORD g_dwOrigFKFlags;
  7. extern BOOL g_bFKOn;
  8. extern LPTSTR HelpFile();
  9. #define SWAP(A, B) ( A ^= B, B ^= A, A ^= B )
  10. // Prototypes
  11. INT_PTR WINAPI BKDlg (HWND, UINT, WPARAM, LPARAM);
  12. INT_PTR WINAPI RKDlg (HWND, UINT, WPARAM, LPARAM);
  13. BOOL WINAPI NotificationDlg (HWND, UINT, WPARAM, LPARAM);
  14. BOOL SubclassFilterKeysTestBox (UINT uIdTestBox,HWND hDlg);
  15. BOOL SubclassRepeatKeysTestBox (UINT uIdTestBox,HWND hDlg);
  16. // All these are for subclassing, so that pressing TAB stops at the next
  17. // control after test areas. a-anilk
  18. LRESULT CALLBACK SubclassWndProcFKPrev(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
  19. LRESULT CALLBACK SubclassWndProcFKNext(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
  20. LRESULT CALLBACK SubclassWndProcRKPrev(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
  21. LRESULT CALLBACK SubclassWndProcRKNext(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
  22. // Times are in milliseconds
  23. #define DELAYSIZE 5
  24. UINT uDelayTable[] = { 300, 700, 1000, 1500, 2000 };
  25. // Times are in milliseconds
  26. #define RATESIZE 6
  27. UINT uRateTable[] = { 300, 500, 700, 1000, 1500, 2000 };
  28. // Times are in milliseconds
  29. #define BOUNCESIZE 5
  30. UINT uBounceTable[] = { 500, 700, 1000, 1500, 2000 };
  31. // Times are in milliseconds
  32. // TODO 5, 10, and 20 sec needs change to kernel code (SystemParametersInfo)
  33. #define ACCEPTSIZE 10
  34. UINT uAcceptTable[] = { 0, 300, 500, 700, 1000, 1400, 2000, 5000, 10000, 20000 };
  35. // these are wndprocs for subclassed windows to ignore repeated tab keys in
  36. // some situations.
  37. WNDPROC g_WndProcFKPrev = NULL;
  38. WNDPROC g_WndProcFKNext = NULL;
  39. WNDPROC g_WndProcRKPrev = NULL;
  40. WNDPROC g_WndProcRKNext = NULL;
  41. // other definitions for the keyboard
  42. // UP means key was up before this message, DOWN means key was down
  43. // PRESS means the key is being pressed, RELEASE means key being released
  44. #define KEY_UP 0
  45. #define KEY_DOWN 1
  46. #define KEY_PRESS 0
  47. #define KEY_RELEASE 1
  48. // Macros to look at the lParam of keyboard messages
  49. //
  50. #define SCAN_CODE(theParam) (LOBYTE (HIWORD(theParam)))
  51. #define EXTENDED(theParam) ( (HIWORD (theParam) & 0x0100) > 0)
  52. #define SYSKEY(theParam) ( (HIWORD (theParam) & 0x2000) > 0)
  53. #define MENUMODE(theParam) ( (HIWORD (theParam) & 0x1000) > 0)
  54. #define PREV_STATE(theParam) ( (HIWORD (theParam) & 0x4000) > 0)
  55. #define TRAN_STATE(theParam) ( (HIWORD (theParam) & 0x8000) > 0)
  56. #define MAKE(theParam) (TRAN_STATE(theParam) == KEY_PRESS)
  57. #define BREAK(theParam) (TRAN_STATE(theParam) == KEY_RELEASE)
  58. #define WASUP(theParam) (PREV_STATE(theParam) == KEY_UP)
  59. #define WASDOWN(theParam) (PREV_STATE(theParam) == KEY_DOWN)
  60. #define FIRSTHIT(theParam) (WASUP(theParam) && MAKE(theParam))
  61. // *************************************************************************
  62. // Process the scrolling messages from our trackbars.
  63. // GENERIC CODE - called for any TrackBar handler.
  64. // Passed in the hwnd, wParam, hwndScroll
  65. // we can do all handling and return the new trackbar value without
  66. // knowing what control it is.
  67. // Returns -1 to mean don't do anything
  68. // *************************************************************************
  69. int HandleScroll (HWND hwnd, WPARAM wParam, HWND hwndScroll) {
  70. int nCurSliderPos = (int) SendMessage(
  71. hwndScroll, TBM_GETPOS, 0, 0);
  72. int nMaxVal = (int) SendMessage(
  73. hwndScroll, TBM_GETRANGEMAX, 0, 0);
  74. int nMinVal = (int) SendMessage(
  75. hwndScroll, TBM_GETRANGEMIN, 0, 0);
  76. switch (LOWORD(wParam)) {
  77. case TB_LINEUP:
  78. case TB_LINEDOWN:
  79. case TB_THUMBTRACK:
  80. case TB_THUMBPOSITION:
  81. case SB_ENDSCROLL:
  82. break;
  83. case TB_BOTTOM:
  84. nCurSliderPos = nMaxVal;
  85. break;
  86. case TB_TOP:
  87. nCurSliderPos = nMinVal;
  88. break;
  89. }
  90. if (nCurSliderPos < nMinVal)
  91. {
  92. nCurSliderPos = nMinVal;
  93. }
  94. if (nCurSliderPos > nMaxVal)
  95. {
  96. nCurSliderPos = nMaxVal;
  97. }
  98. SendMessage(GetParent(hwnd), PSM_CHANGED, (WPARAM) hwnd, 0);
  99. return(nCurSliderPos);
  100. }
  101. // Helper functions
  102. __inline WriteFloat(LPTSTR pszBuf, UINT uVal, LPCTSTR pszUnits)
  103. {
  104. wsprintf(pszBuf, TEXT("%d.%d %s"), uVal/1000, (uVal % 1000)/100, pszUnits);
  105. }
  106. __inline void HandleSelection(HWND hwnd, UINT *puTable, DWORD *pdwNewValue)
  107. {
  108. LRESULT i = SendMessage(hwnd, CB_GETCURSEL, 0, 0);
  109. *pdwNewValue = (i != CB_ERR)?puTable[i]:0;
  110. }
  111. int GetIndex(DWORD dwValue, UINT *puTable, int cSize)
  112. {
  113. int i;
  114. for (i = 0; i < cSize; i++)
  115. {
  116. if (puTable[i] >= dwValue)
  117. break;
  118. }
  119. if (i >= cSize)
  120. i = cSize - 1;
  121. return i;
  122. }
  123. void FillAndSetCombo(HWND hwnd, UINT *puTable, int cItems, int iCurPos, LPCTSTR pszUnits)
  124. {
  125. int i;
  126. TCHAR pszItem[100];
  127. SendMessage(hwnd, CB_RESETCONTENT, 0, 0);
  128. for (i=0;i<cItems;i++)
  129. {
  130. WriteFloat(pszItem, puTable[i], pszUnits);
  131. SendMessage(hwnd, CB_ADDSTRING, 0, (LPARAM)pszItem);
  132. }
  133. SendMessage(hwnd, CB_SETCURSEL, iCurPos, 0);
  134. }
  135. void TestFilterKeys (BOOL fTurnTestOn)
  136. {
  137. if (fTurnTestOn)
  138. {
  139. g_fk.dwFlags &= ~FKF_INDICATOR;
  140. g_fk.dwFlags |= FKF_FILTERKEYSON;
  141. }
  142. else
  143. {
  144. if (g_dwOrigFKFlags & FKF_FILTERKEYSON)
  145. {
  146. g_fk.dwFlags |= FKF_FILTERKEYSON;
  147. }
  148. else
  149. {
  150. g_fk.dwFlags &= ~FKF_FILTERKEYSON;
  151. }
  152. if (g_dwOrigFKFlags & FKF_INDICATOR)
  153. {
  154. g_fk.dwFlags |= FKF_INDICATOR;
  155. }
  156. else
  157. {
  158. g_fk.dwFlags &= ~FKF_INDICATOR;
  159. }
  160. }
  161. AccessSystemParametersInfo(SPI_SETFILTERKEYS, sizeof(g_fk), &g_fk, 0);
  162. }
  163. // ****************************************************************************
  164. // Main filter keys dialog handler
  165. // ****************************************************************************
  166. INT_PTR WINAPI FilterKeyDlg (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  167. FILTERKEYS fk;
  168. BOOL fProcessed = TRUE;
  169. switch (uMsg) {
  170. case WM_INITDIALOG:
  171. // Setup hotkey
  172. CheckDlgButton(hwnd, IDC_FK_HOTKEY, (g_fk.dwFlags & FKF_HOTKEYACTIVE) ? TRUE : FALSE);
  173. // Setup the radio buttons for SLOW vs BOUNCE keys
  174. if (0 != g_fk.iBounceMSec) {
  175. // Bounce keys enabeled
  176. CheckRadioButton(hwnd, IDC_FK_BOUNCE, IDC_FK_REPEAT, IDC_FK_BOUNCE);
  177. EnableWindow(GetDlgItem(hwnd, IDC_BK_SETTINGS), TRUE);
  178. EnableWindow(GetDlgItem(hwnd, IDC_RK_SETTINGS), FALSE);
  179. }
  180. else
  181. {
  182. // Slow key enabled
  183. CheckRadioButton(hwnd, IDC_FK_BOUNCE, IDC_FK_REPEAT, IDC_FK_REPEAT);
  184. EnableWindow(GetDlgItem(hwnd, IDC_BK_SETTINGS), FALSE);
  185. EnableWindow(GetDlgItem(hwnd, IDC_RK_SETTINGS), TRUE);
  186. }
  187. CheckDlgButton(hwnd, IDC_FK_SOUND, (g_fk.dwFlags & FKF_CLICKON) ? TRUE : FALSE);
  188. CheckDlgButton(hwnd, IDC_FK_STATUS, (g_fk.dwFlags & FKF_INDICATOR) ? TRUE : FALSE);
  189. //
  190. // SteveDon 5/15/98
  191. // If the focus is in the TestBox and "Ignore Quick Keystrokes" is on,
  192. // you have to hold down tab to get out. But as soon as focus leaves,
  193. // Ignore Quick Keystrokes gets turned off and the tab keys ends up
  194. // autorepeating very quickly, which (usually) lands you back in the
  195. // TestBox.
  196. // Solution: ignore repeated tabs in this dialog.
  197. // Problem: keys don't go to the dialog, they go to the focused
  198. // control. So: we can try to ignore repeated tab keys for the controls
  199. // just after the test box and just before the test box, which means
  200. // that we need to subclass those window procs.
  201. if (!SubclassFilterKeysTestBox (IDC_FK_TESTBOX,hwnd))
  202. return (FALSE);
  203. break;
  204. case WM_HELP:
  205. WinHelp(((LPHELPINFO) lParam)->hItemHandle, HelpFile(), HELP_WM_HELP, (DWORD_PTR) (LPSTR) g_aIds);
  206. break;
  207. case WM_CONTEXTMENU:
  208. WinHelp((HWND) wParam, HelpFile(), HELP_CONTEXTMENU, (DWORD_PTR) (LPSTR) g_aIds);
  209. break;
  210. case WM_COMMAND:
  211. switch (GET_WM_COMMAND_ID(wParam, lParam)) {
  212. case IDC_FK_HOTKEY:
  213. g_fk.dwFlags ^= FKF_HOTKEYACTIVE;
  214. break;
  215. case IDC_FK_REPEAT:
  216. g_fk.iBounceMSec = 0;
  217. if (g_fk.iDelayMSec == 0)
  218. {
  219. g_fk.iDelayMSec = g_nLastRepeatDelay;
  220. g_fk.iRepeatMSec = g_nLastRepeatRate;
  221. g_fk.iWaitMSec = g_nLastWait;
  222. }
  223. CheckRadioButton(hwnd, IDC_FK_REPEAT, IDC_FK_BOUNCE, IDC_FK_REPEAT);
  224. EnableWindow(GetDlgItem(hwnd, IDC_BK_SETTINGS), FALSE);
  225. EnableWindow(GetDlgItem(hwnd, IDC_RK_SETTINGS), TRUE);
  226. break;
  227. case IDC_FK_BOUNCE:
  228. g_fk.iDelayMSec = 0;
  229. g_fk.iRepeatMSec = 0;
  230. g_fk.iWaitMSec = 0;
  231. if (g_fk.iBounceMSec == 0)
  232. {
  233. g_fk.iBounceMSec = g_dwLastBounceKeySetting;
  234. }
  235. CheckRadioButton(hwnd, IDC_FK_REPEAT, IDC_FK_BOUNCE, IDC_FK_BOUNCE);
  236. EnableWindow(GetDlgItem(hwnd, IDC_BK_SETTINGS), TRUE);
  237. EnableWindow(GetDlgItem(hwnd, IDC_RK_SETTINGS), FALSE);
  238. break;
  239. // Settings dialogs
  240. case IDC_RK_SETTINGS: // This is RepeatKeys
  241. fk = g_fk;
  242. if (DialogBox(g_hinst, MAKEINTRESOURCE(IDD_ADVCHARREPEAT), hwnd, RKDlg) == IDCANCEL) {
  243. g_fk = fk;
  244. }
  245. break;
  246. case IDC_BK_SETTINGS: // This is BounceKeys
  247. fk = g_fk;
  248. if (DialogBox(g_hinst, MAKEINTRESOURCE(IDD_ADVKEYBOUNCE), hwnd, BKDlg) == IDCANCEL) {
  249. g_fk = fk;
  250. }
  251. break;
  252. case IDC_FK_SOUND:
  253. g_fk.dwFlags ^= FKF_CLICKON;
  254. break;
  255. case IDC_FK_STATUS:
  256. g_fk.dwFlags ^= FKF_INDICATOR;
  257. break;
  258. // The test edit box is a special control for us. When we get the
  259. // focus we turn on the current filterkeys settings, when we
  260. // leave the text box, we turn them back to what they were.
  261. case IDC_FK_TESTBOX:
  262. switch (HIWORD(wParam)) {
  263. case EN_SETFOCUS: TestFilterKeys(TRUE); break;
  264. case EN_KILLFOCUS: TestFilterKeys(FALSE); break;
  265. }
  266. break;
  267. case IDOK:
  268. if (g_dwLastBounceKeySetting == 0)
  269. g_dwLastBounceKeySetting = uBounceTable[0];
  270. EndDialog(hwnd, IDOK);
  271. break;
  272. case IDCANCEL:
  273. EndDialog(hwnd, IDCANCEL);
  274. break;
  275. }
  276. break;
  277. default:
  278. fProcessed = FALSE; break;
  279. }
  280. return(fProcessed);
  281. }
  282. void PutNumInEdit (HWND hwndEdit, int nNum)
  283. {
  284. TCHAR szBuf[10], szBuf2[20];
  285. wsprintf(szBuf, __TEXT("%d.%d"), nNum / 1000, (nNum % 1000) / 100);
  286. GetNumberFormat(LOCALE_USER_DEFAULT, 0, szBuf, NULL, szBuf2, 20);
  287. SetWindowText(hwndEdit, szBuf2);
  288. }
  289. // **************************************************************************
  290. // BKDlg
  291. // Process the BounceKeys dialog.
  292. // **************************************************************************
  293. INT_PTR WINAPI BKDlg (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  294. int i;
  295. BOOL fProcessed = TRUE;
  296. TCHAR pszSeconds[50];
  297. int ctch;
  298. switch (uMsg) {
  299. case WM_INITDIALOG:
  300. ctch = LoadString(g_hinst, IDS_SECONDS, pszSeconds, ARRAY_SIZE(pszSeconds));
  301. Assert(ctch);
  302. // Determine the bounce. Make sure its a valide value.
  303. if (g_dwLastBounceKeySetting == 0)
  304. g_dwLastBounceKeySetting = 500;
  305. if (g_fk.iBounceMSec == 0)
  306. g_fk.iBounceMSec = g_dwLastBounceKeySetting;
  307. i = GetIndex(g_fk.iBounceMSec, uBounceTable, BOUNCESIZE);
  308. FillAndSetCombo(GetDlgItem(hwnd, IDC_CMB_BK_BOUNCERATE), uBounceTable, BOUNCESIZE, i, pszSeconds);
  309. break;
  310. case WM_HELP: // F1
  311. WinHelp(((LPHELPINFO) lParam)->hItemHandle, HelpFile(), HELP_WM_HELP, (DWORD_PTR) (LPSTR) g_aIds);
  312. break;
  313. case WM_CONTEXTMENU: // right mouse click
  314. WinHelp((HWND) wParam, HelpFile(), HELP_CONTEXTMENU, (DWORD_PTR) (LPSTR) g_aIds);
  315. break;
  316. case WM_COMMAND:
  317. switch (GET_WM_COMMAND_ID(wParam, lParam)) {
  318. // The test edit box is a special control for us. When we get the
  319. // focus we turn on the current filterkeys settings, when we
  320. // leave the text box, we turn them back to what they were.
  321. case IDC_BK_TESTBOX:
  322. switch (HIWORD(wParam)) {
  323. case EN_SETFOCUS: TestFilterKeys(TRUE); break;
  324. case EN_KILLFOCUS: TestFilterKeys(FALSE); break;
  325. }
  326. break;
  327. case IDC_CMB_BK_BOUNCERATE:
  328. switch (HIWORD(wParam))
  329. {
  330. case CBN_SELCHANGE:
  331. HandleSelection(GetDlgItem(hwnd, IDC_CMB_BK_BOUNCERATE), uBounceTable, &g_fk.iBounceMSec);
  332. break;
  333. }
  334. break;
  335. case IDOK:
  336. // Save the last known valid setting.
  337. g_dwLastBounceKeySetting = g_fk.iBounceMSec;
  338. EndDialog(hwnd, IDOK);
  339. break;
  340. case IDCANCEL:
  341. EndDialog(hwnd, IDCANCEL);
  342. break;
  343. }
  344. break;
  345. default: fProcessed = FALSE; break;
  346. }
  347. return(fProcessed);
  348. }
  349. // **************************************************************************
  350. // RKDlg
  351. // Process the RepeatKeys dialog.
  352. // **************************************************************************
  353. INT_PTR WINAPI RKDlg (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  354. int i;
  355. BOOL fProcessed = TRUE;
  356. static s_fRepeating = TRUE;
  357. static DWORD s_nLastRepeatDelayOld;
  358. static DWORD s_nLastRepeatRateOld;
  359. static DWORD s_nLastWaitOld;
  360. TCHAR pszItem[100];
  361. TCHAR pszSeconds[50];
  362. int ctch;
  363. LPARAM lParamT;
  364. switch(uMsg) {
  365. case WM_INITDIALOG:
  366. ctch = LoadString(g_hinst, IDS_SECONDS, pszSeconds, ARRAY_SIZE(pszSeconds));
  367. Assert(ctch);
  368. s_nLastRepeatDelayOld = g_nLastRepeatDelay;
  369. s_nLastRepeatRateOld = g_nLastRepeatRate;
  370. s_nLastWaitOld = g_nLastWait;
  371. s_fRepeating = (0 != g_fk.iDelayMSec);
  372. CheckRadioButton(hwnd, IDC_RK_NOREPEAT, IDC_RK_REPEAT,
  373. s_fRepeating ? IDC_RK_REPEAT : IDC_RK_NOREPEAT);
  374. if (!s_fRepeating) {
  375. // Set FilterKey values to LastRepeat values
  376. // so the sliders will still get initialized correctly
  377. g_fk.iDelayMSec = g_nLastRepeatDelay;
  378. g_fk.iRepeatMSec = g_nLastRepeatRate;
  379. }
  380. // Initialize the Acceptance combo box to last valid state
  381. i = GetIndex(g_fk.iWaitMSec, uAcceptTable, ACCEPTSIZE);
  382. FillAndSetCombo(GetDlgItem(hwnd, IDC_CMB_RK_ACCEPTRATE), uAcceptTable, ACCEPTSIZE, i, pszSeconds);
  383. g_fk.iWaitMSec = uAcceptTable[i];
  384. // Initialize the Delay combo box
  385. i = GetIndex(g_fk.iDelayMSec, uDelayTable, DELAYSIZE);
  386. FillAndSetCombo(GetDlgItem(hwnd, IDC_CMB_RK_DELAYRATE), uDelayTable, DELAYSIZE, i, pszSeconds);
  387. g_fk.iDelayMSec = uDelayTable[i];
  388. // Initialize the Repeat Rate Slider Note -1 is set via the checkbox.
  389. i = GetIndex(g_fk.iRepeatMSec, uRateTable, RATESIZE);
  390. FillAndSetCombo(GetDlgItem(hwnd, IDC_CMB_RK_REPEATRATE), uRateTable, RATESIZE, i, pszSeconds);
  391. g_fk.iRepeatMSec = uRateTable[i];
  392. // Now cleanup from initialization. Disable controls
  393. // that usable... Swap back any params needed
  394. if (!s_fRepeating)
  395. {
  396. EnableWindow(GetDlgItem(hwnd, IDC_CMB_RK_REPEATRATE), FALSE);
  397. EnableWindow(GetDlgItem(hwnd, IDC_CMB_RK_DELAYRATE), FALSE);
  398. // If we're not repeating, now set the value to 0
  399. // which indicates max repeat rate.
  400. g_fk.iDelayMSec = 0;
  401. g_fk.iRepeatMSec = 0;
  402. }
  403. //
  404. // SteveDon 5/15/98
  405. // If the focus is in the TestBox and "Ignore Quick Keystrokes" is on,
  406. // you have to hold down tab to get out. But as soon as focus leaves,
  407. // Ignore Quick Keystrokes gets turned off and the tab keys ends up
  408. // autorepeating very quickly, which (usually) lands you back in the
  409. // TestBox.
  410. // Solution: ignore repeated tabs in this dialog.
  411. // Problem: keys don't go to the dialog, they go to the focused
  412. // control. So: we can try to ignore repeated tab keys for the controls
  413. // just after the test box and just before the test box, which means
  414. // that we need to subclass those window procs.
  415. if (!SubclassRepeatKeysTestBox (IDC_RK_TESTBOX,hwnd))
  416. return (FALSE);
  417. break;
  418. case WM_HELP: // F1
  419. WinHelp(((LPHELPINFO) lParam)->hItemHandle, HelpFile(), HELP_WM_HELP, (DWORD_PTR) (LPSTR) g_aIds);
  420. break;
  421. case WM_CONTEXTMENU: // right mouse click
  422. WinHelp((HWND) wParam, HelpFile(), HELP_CONTEXTMENU, (DWORD_PTR) (LPSTR) g_aIds);
  423. break;
  424. case WM_COMMAND:
  425. switch (GET_WM_COMMAND_ID(wParam, lParam)) {
  426. // Turn on repeat keys - We're disabling via CPL rather than any flags in the call
  427. case IDC_RK_REPEAT:
  428. if (!s_fRepeating) {
  429. g_fk.iDelayMSec = g_nLastRepeatDelay;
  430. g_fk.iRepeatMSec = g_nLastRepeatRate;
  431. }
  432. // Now that we have valid parameters, continue with setting the sliders.
  433. s_fRepeating = TRUE;
  434. CheckRadioButton(hwnd, IDC_RK_NOREPEAT, IDC_RK_REPEAT, IDC_RK_REPEAT);
  435. if (g_fk.iRepeatMSec == 0)
  436. g_fk.iRepeatMSec = uRateTable[0];
  437. if (g_fk.iDelayMSec == 0)
  438. g_fk.iDelayMSec = uDelayTable[0];
  439. i = GetIndex(g_fk.iRepeatMSec, uRateTable, RATESIZE);
  440. EnableWindow(GetDlgItem(hwnd, IDC_CMB_RK_REPEATRATE), TRUE);
  441. SendDlgItemMessage(hwnd, IDC_CMB_RK_REPEATRATE, CB_SETCURSEL, i, 0);
  442. i = GetIndex(g_fk.iDelayMSec, uDelayTable, DELAYSIZE);
  443. EnableWindow(GetDlgItem(hwnd, IDC_CMB_RK_DELAYRATE), TRUE);
  444. SendDlgItemMessage(hwnd, IDC_CMB_RK_DELAYRATE, CB_SETCURSEL, i, 0);
  445. break;
  446. // Turn OFF repeat keys
  447. case IDC_RK_NOREPEAT:
  448. s_fRepeating = FALSE;
  449. CheckRadioButton(hwnd, IDC_RK_NOREPEAT, IDC_RK_REPEAT, IDC_RK_NOREPEAT);
  450. g_fk.iDelayMSec = 0;
  451. g_fk.iRepeatMSec = 0;
  452. SendDlgItemMessage(hwnd, IDC_CMB_RK_DELAYRATE, CB_SETCURSEL, -1, 0);
  453. EnableWindow(GetDlgItem(hwnd, IDC_CMB_RK_DELAYRATE), FALSE);
  454. SendDlgItemMessage(hwnd, IDC_CMB_RK_REPEATRATE, CB_SETCURSEL, -1, 0);
  455. EnableWindow(GetDlgItem(hwnd, IDC_CMB_RK_REPEATRATE), FALSE);
  456. break;
  457. // Process the test box - turnon filterkeys while inside it.
  458. case IDC_RK_TESTBOX:
  459. switch (HIWORD(wParam)) {
  460. case EN_SETFOCUS: TestFilterKeys(TRUE); break;
  461. case EN_KILLFOCUS: TestFilterKeys(FALSE); break;
  462. }
  463. break;
  464. case IDC_CMB_RK_DELAYRATE:
  465. switch (HIWORD(wParam))
  466. {
  467. case CBN_SELCHANGE:
  468. HandleSelection(GetDlgItem(hwnd, IDC_CMB_RK_DELAYRATE), uDelayTable, &g_fk.iDelayMSec);
  469. break;
  470. }
  471. break;
  472. case IDC_CMB_RK_REPEATRATE:
  473. switch (HIWORD(wParam))
  474. {
  475. case CBN_SELCHANGE:
  476. HandleSelection(GetDlgItem(hwnd, IDC_CMB_RK_REPEATRATE), uRateTable, &g_fk.iRepeatMSec);
  477. break;
  478. }
  479. break;
  480. case IDC_CMB_RK_ACCEPTRATE:
  481. switch (HIWORD(wParam))
  482. {
  483. case CBN_SELCHANGE:
  484. HandleSelection(GetDlgItem(hwnd, IDC_CMB_RK_ACCEPTRATE), uAcceptTable, &g_fk.iWaitMSec);
  485. break;
  486. }
  487. break;
  488. case IDOK:
  489. // Save off repeating values to registry
  490. EndDialog(hwnd, IDOK);
  491. break;
  492. case IDCANCEL:
  493. g_nLastRepeatDelay = s_nLastRepeatDelayOld;
  494. g_nLastRepeatRate = s_nLastRepeatRateOld;
  495. g_nLastWait = s_nLastWaitOld;
  496. EndDialog(hwnd, IDCANCEL);
  497. break;
  498. }
  499. break;
  500. default:
  501. fProcessed = FALSE;
  502. break;
  503. }
  504. return(fProcessed);
  505. }
  506. // **************************************************************************
  507. // SubclassFilterKeysTestBox
  508. //
  509. // This takes the dialog ID of an edit field, and then finds the controls
  510. // near the edit field (the controls 2 windows before and 2 windows after the
  511. // edit control in the z-order). These are the nearest controls that get
  512. // keyboard messages. It subclasses both of these controls
  513. // so that they ignore any WM_KEYDOWN messages when the key being pressed is
  514. // the tab key and the key is already down (i.e. this is a repeated message)
  515. //
  516. // **************************************************************************
  517. BOOL SubclassFilterKeysTestBox (UINT uIdTestBox,HWND hDlg)
  518. {
  519. HWND hwndPrev,
  520. hwndNext,
  521. hwndTestBox;
  522. hwndTestBox = GetDlgItem (hDlg,uIdTestBox);
  523. // BE CAREFUL IF DIALOG CHANGES! Right now the
  524. // Previous Previous window is the "S&ettings" push button,
  525. // and the Next Next is the "&Beep when keys pressed..."
  526. // checkbox. If the order changes, this code might have to change too.
  527. // Could make it more general where it searches for controls before
  528. // and after that can get keyboard focus.
  529. hwndPrev = GetNextDlgTabItem (hDlg,hwndTestBox,TRUE);
  530. if (!hwndPrev)
  531. return FALSE;
  532. g_WndProcFKPrev = (WNDPROC) GetWindowLongPtr (hwndPrev, GWLP_WNDPROC);
  533. SetWindowLongPtr (hwndPrev,GWLP_WNDPROC,(LPARAM)SubclassWndProcFKPrev);
  534. hwndNext = GetNextDlgTabItem (hDlg,hwndTestBox,FALSE);
  535. if (!hwndNext)
  536. return FALSE;
  537. g_WndProcFKNext = (WNDPROC) GetWindowLongPtr (hwndNext, GWLP_WNDPROC);
  538. SetWindowLongPtr (hwndNext,GWLP_WNDPROC,(LPARAM)SubclassWndProcFKNext);
  539. return TRUE;
  540. }
  541. // **************************************************************************
  542. // SubclassWndProcFKPrev
  543. //
  544. // This is the WndProc used to ignore repeated presses of the tab key for
  545. // the first focusable control that precedes the test box.
  546. //
  547. // **************************************************************************
  548. LRESULT CALLBACK SubclassWndProcFKPrev(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
  549. {
  550. switch (uMsg)
  551. {
  552. case WM_KEYDOWN:
  553. if ((int)wParam == VK_TAB)
  554. {
  555. if (WASDOWN (lParam))
  556. {
  557. return (0);
  558. }
  559. // if not a repeat, need to move the focus. For some reason,
  560. // just calling CallWindowProc won't do it for us.
  561. if (GetKeyState(VK_SHIFT) < 0)
  562. {
  563. SendMessage (GetParent(hwnd),WM_NEXTDLGCTL,1,0);
  564. }
  565. else
  566. {
  567. SendMessage (GetParent(hwnd),WM_NEXTDLGCTL,0,0);
  568. }
  569. }
  570. break;
  571. case WM_GETDLGCODE:
  572. return (DLGC_WANTTAB | CallWindowProc (g_WndProcFKPrev,hwnd,uMsg,wParam,lParam));
  573. break;
  574. }
  575. return (CallWindowProc(g_WndProcFKPrev,hwnd,uMsg,wParam,lParam));
  576. }
  577. // **************************************************************************
  578. // SubclassWndProcFKNext
  579. //
  580. // This is the WndProc used to ignore repeated presses of the tab key for
  581. // the first focusable control that follows the test box.
  582. //
  583. // **************************************************************************
  584. LRESULT CALLBACK SubclassWndProcFKNext(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
  585. {
  586. switch (uMsg)
  587. {
  588. case WM_KEYDOWN:
  589. if ((int)wParam == VK_TAB)
  590. {
  591. if (WASDOWN(lParam))
  592. {
  593. return (0);
  594. }
  595. // if not a repeat, need to move the focus. For some reason,
  596. // just calling CallWindowProc won't do it for us.
  597. if (GetKeyState(VK_SHIFT) < 0)
  598. {
  599. SendMessage (GetParent(hwnd),WM_NEXTDLGCTL,1,0);
  600. }
  601. else
  602. {
  603. SendMessage (GetParent(hwnd),WM_NEXTDLGCTL,0,0);
  604. }
  605. }
  606. break;
  607. case WM_GETDLGCODE:
  608. return (DLGC_WANTTAB | CallWindowProc (g_WndProcFKNext,hwnd,uMsg,wParam,lParam));
  609. break;
  610. }
  611. return (CallWindowProc(g_WndProcFKNext,hwnd,uMsg,wParam,lParam));
  612. }
  613. // **************************************************************************
  614. // SubclassRepeatKeysTestBox
  615. //
  616. // Same as SubclassFilterKeysTestBox, but keeps it's info in different
  617. // globals so that one doesn't overwrite the other.
  618. //
  619. // **************************************************************************
  620. BOOL SubclassRepeatKeysTestBox (UINT uIdTestBox,HWND hDlg)
  621. {
  622. HWND hwndPrev,
  623. hwndNext,
  624. hwndTestBox;
  625. hwndTestBox = GetDlgItem (hDlg,uIdTestBox);
  626. // BE CAREFUL IF DIALOG CHANGES! Right now the
  627. // Previous Previous window is the "S&ettings" push button,
  628. // and the Next Next is the "&Beep when keys pressed..."
  629. // checkbox. If the order changes, this code might have to change too.
  630. // Could make it more general where it searches for controls before
  631. // and after that can get keyboard focus.
  632. hwndPrev = GetNextDlgTabItem (hDlg,hwndTestBox,TRUE);
  633. g_WndProcRKPrev = (WNDPROC) GetWindowLongPtr (hwndPrev,GWLP_WNDPROC);
  634. SetWindowLongPtr (hwndPrev,GWLP_WNDPROC,(LPARAM)SubclassWndProcRKPrev);
  635. hwndNext = GetNextDlgTabItem (hDlg,hwndTestBox,FALSE);
  636. g_WndProcRKNext = (WNDPROC) GetWindowLongPtr (hwndNext,GWLP_WNDPROC);
  637. SetWindowLongPtr (hwndNext,GWLP_WNDPROC,(LPARAM)SubclassWndProcRKNext);
  638. return (TRUE);
  639. }
  640. // **************************************************************************
  641. // SubclassWndProcRKPrev
  642. //
  643. // **************************************************************************
  644. LRESULT CALLBACK SubclassWndProcRKPrev(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
  645. {
  646. switch (uMsg)
  647. {
  648. case WM_KEYDOWN:
  649. if ((int)wParam == VK_TAB)
  650. {
  651. if (WASDOWN (lParam))
  652. {
  653. return (0);
  654. }
  655. // if not a repeat, need to move the focus. For some reason,
  656. // just calling CallWindowProc won't do it for us.
  657. if (GetKeyState(VK_SHIFT) < 0)
  658. {
  659. SendMessage (GetParent(hwnd),WM_NEXTDLGCTL,1,0);
  660. }
  661. else
  662. {
  663. SendMessage (GetParent(hwnd),WM_NEXTDLGCTL,0,0);
  664. }
  665. }
  666. break;
  667. case WM_GETDLGCODE:
  668. return (DLGC_WANTTAB | CallWindowProc (g_WndProcRKPrev,hwnd,uMsg,wParam,lParam));
  669. break;
  670. }
  671. return (CallWindowProc(g_WndProcRKPrev,hwnd,uMsg,wParam,lParam));
  672. }
  673. // **************************************************************************
  674. // SubclassWndProcRKNext
  675. //
  676. // **************************************************************************
  677. LRESULT CALLBACK SubclassWndProcRKNext(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
  678. {
  679. switch (uMsg)
  680. {
  681. case WM_KEYDOWN:
  682. if ((int)wParam == VK_TAB)
  683. {
  684. if (WASDOWN(lParam))
  685. {
  686. return (0);
  687. }
  688. // if not a repeat, need to move the focus. For some reason,
  689. // just calling CallWindowProc won't do it for us.
  690. if (GetKeyState(VK_SHIFT) < 0)
  691. {
  692. SendMessage (GetParent(hwnd),WM_NEXTDLGCTL,1,0);
  693. }
  694. else
  695. {
  696. SendMessage (GetParent(hwnd),WM_NEXTDLGCTL,0,0);
  697. }
  698. }
  699. break;
  700. case WM_GETDLGCODE:
  701. return (DLGC_WANTTAB | CallWindowProc (g_WndProcRKNext,hwnd,uMsg,wParam,lParam));
  702. break;
  703. }
  704. return (CallWindowProc(g_WndProcRKNext,hwnd,uMsg,wParam,lParam));
  705. }
  706. ///////////////////////////////// End of File /////////////////////////////////