2 * PROJECT: ReactOS Accessibility Control Panel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/cpl/access/keyboard.c
5 * PURPOSE: Keyboard-related accessibility settings
6 * COPYRIGHT: Copyright 2004 Johannes Anderwald (j_anderw@sbox.tugraz.at)
7 * Copyright 2007 Eric Kohl
14 static UINT nBounceArray
[BOUNCETICKS
] = {500, 700, 1000, 1500, 2000};
17 static UINT nDelayArray
[DELAYTICKS
] = {300, 700, 1000, 1500, 2000};
20 static UINT nRepeatArray
[REPEATTICKS
] = {300, 500, 700, 1000, 1500, 2000};
23 static UINT nWaitArray
[WAITTICKS
] = {0, 300, 500, 700, 1000, 1500, 2000, 5000, 10000, 20000};
27 EnableFilterKeysTest(PGLOBAL_DATA pGlobalData
)
29 pGlobalData
->filterKeys
.dwFlags
|= FKF_FILTERKEYSON
;
30 pGlobalData
->filterKeys
.dwFlags
&= ~FKF_INDICATOR
;
32 SystemParametersInfo(SPI_SETFILTERKEYS
,
34 &pGlobalData
->filterKeys
,
40 DisableFilterKeysTest(PGLOBAL_DATA pGlobalData
)
42 if (pGlobalData
->oldFilterKeys
.dwFlags
& FKF_FILTERKEYSON
)
44 pGlobalData
->filterKeys
.dwFlags
|= FKF_FILTERKEYSON
;
48 pGlobalData
->filterKeys
.dwFlags
&= ~FKF_FILTERKEYSON
;
51 if (pGlobalData
->oldFilterKeys
.dwFlags
& FKF_INDICATOR
)
53 pGlobalData
->filterKeys
.dwFlags
|= FKF_INDICATOR
;
57 pGlobalData
->filterKeys
.dwFlags
&= ~FKF_INDICATOR
;
60 SystemParametersInfo(SPI_SETFILTERKEYS
,
62 &pGlobalData
->filterKeys
,
67 /* Property page dialog callback */
69 StickyKeysDlgProc(HWND hwndDlg
,
74 PGLOBAL_DATA pGlobalData
;
76 pGlobalData
= (PGLOBAL_DATA
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
81 pGlobalData
= (PGLOBAL_DATA
)lParam
;
82 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pGlobalData
);
84 memcpy(&pGlobalData
->oldStickyKeys
,
85 &pGlobalData
->stickyKeys
,
88 CheckDlgButton(hwndDlg
,
89 IDC_STICKY_ACTIVATE_CHECK
,
90 pGlobalData
->stickyKeys
.dwFlags
& SKF_HOTKEYACTIVE
? BST_CHECKED
: BST_UNCHECKED
);
92 CheckDlgButton(hwndDlg
,
93 IDC_STICKY_LOCK_CHECK
,
94 pGlobalData
->stickyKeys
.dwFlags
& SKF_TRISTATE
? BST_CHECKED
: BST_UNCHECKED
);
96 CheckDlgButton(hwndDlg
,
97 IDC_STICKY_UNLOCK_CHECK
,
98 pGlobalData
->stickyKeys
.dwFlags
& SKF_TWOKEYSOFF
? BST_CHECKED
: BST_UNCHECKED
);
100 CheckDlgButton(hwndDlg
,
101 IDC_STICKY_SOUND_CHECK
,
102 pGlobalData
->stickyKeys
.dwFlags
& SKF_AUDIBLEFEEDBACK
? BST_CHECKED
: BST_UNCHECKED
);
104 CheckDlgButton(hwndDlg
,
105 IDC_STICKY_STATUS_CHECK
,
106 pGlobalData
->stickyKeys
.dwFlags
& SKF_INDICATOR
? BST_CHECKED
: BST_UNCHECKED
);
110 switch (LOWORD(wParam
))
112 case IDC_STICKY_ACTIVATE_CHECK
:
113 pGlobalData
->stickyKeys
.dwFlags
^= SKF_HOTKEYACTIVE
;
116 case IDC_STICKY_LOCK_CHECK
:
117 pGlobalData
->stickyKeys
.dwFlags
^= SKF_TRISTATE
;
120 case IDC_STICKY_UNLOCK_CHECK
:
121 pGlobalData
->stickyKeys
.dwFlags
^= SKF_TWOKEYSOFF
;
124 case IDC_STICKY_SOUND_CHECK
:
125 pGlobalData
->stickyKeys
.dwFlags
^= SKF_AUDIBLEFEEDBACK
;
128 case IDC_STICKY_STATUS_CHECK
:
129 pGlobalData
->stickyKeys
.dwFlags
^= SKF_INDICATOR
;
134 (pGlobalData
->stickyKeys
.dwFlags
!= pGlobalData
->oldStickyKeys
.dwFlags
));
138 EndDialog(hwndDlg
, FALSE
);
152 AddComboBoxTime(HWND hwnd
, INT nId
, INT nTimeMs
)
157 if (LoadString(hApplet
, IDS_SECONDS
, szSeconds
, 20) == 0)
158 lstrcpy(szSeconds
, L
"Seconds");
160 _stprintf(szBuffer
, _T("%d.%d %s"),
161 nTimeMs
/ 1000, (nTimeMs
% 1000) / 100,
164 SendDlgItemMessage(hwnd
, nId
, CB_ADDSTRING
, 0, (LPARAM
)szBuffer
);
169 BounceKeysDlgProc(HWND hwndDlg
,
174 PGLOBAL_DATA pGlobalData
;
177 pGlobalData
= (PGLOBAL_DATA
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
182 pGlobalData
= (PGLOBAL_DATA
)lParam
;
183 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pGlobalData
);
185 /* Determine the current bounce time */
186 if (pGlobalData
->filterKeys
.iBounceMSec
== 0)
187 pGlobalData
->filterKeys
.iBounceMSec
= nBounceArray
[0];
189 for (n
= 0; n
< BOUNCETICKS
; n
++)
191 if (pGlobalData
->filterKeys
.iBounceMSec
< nBounceArray
[n
])
196 for (i
= 0; i
< BOUNCETICKS
; i
++)
198 AddComboBoxTime(hwndDlg
, IDC_BOUNCE_TIME_COMBO
, nBounceArray
[i
]);
201 SendDlgItemMessage(hwndDlg
, IDC_BOUNCE_TIME_COMBO
, CB_SETCURSEL
, n
, 0);
205 switch (LOWORD(wParam
))
207 case IDC_BOUNCE_TIME_COMBO
:
208 if (HIWORD(wParam
) == CBN_SELCHANGE
)
210 i
= SendDlgItemMessage(hwndDlg
, IDC_BOUNCE_TIME_COMBO
, CB_GETCURSEL
, 0, 0);
213 pGlobalData
->filterKeys
.iBounceMSec
= nBounceArray
[i
];
218 case IDC_BOUNCE_TEST_EDIT
:
219 switch (HIWORD(wParam
))
222 EnableFilterKeysTest(pGlobalData
);
226 DisableFilterKeysTest(pGlobalData
);
232 EndDialog(hwndDlg
, TRUE
);
236 EndDialog(hwndDlg
, FALSE
);
250 RepeatKeysDlgProc(HWND hwndDlg
,
255 PGLOBAL_DATA pGlobalData
;
258 pGlobalData
= (PGLOBAL_DATA
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
263 pGlobalData
= (PGLOBAL_DATA
)lParam
;
264 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pGlobalData
);
266 CheckRadioButton(hwndDlg
,
267 IDC_REPEAT_NOREPEAT_RADIO
,
268 IDC_REPEAT_REPEAT_RADIO
,
269 (pGlobalData
->filterKeys
.iDelayMSec
== 0) ? IDC_REPEAT_NOREPEAT_RADIO
: IDC_REPEAT_REPEAT_RADIO
);
271 /* Initialize the delay combobox */
272 for (n
= 0; n
< DELAYTICKS
; n
++)
274 if (pGlobalData
->filterKeys
.iDelayMSec
< nDelayArray
[n
])
279 for (i
= 0; i
< DELAYTICKS
; i
++)
281 AddComboBoxTime(hwndDlg
, IDC_REPEAT_DELAY_COMBO
, nDelayArray
[i
]);
284 SendDlgItemMessage(hwndDlg
, IDC_REPEAT_DELAY_COMBO
, CB_SETCURSEL
, n
, 0);
286 /* Initialize the repeat combobox */
287 for (n
= 0; n
< REPEATTICKS
; n
++)
289 if (pGlobalData
->filterKeys
.iRepeatMSec
< nRepeatArray
[n
])
294 for (i
= 0; i
< REPEATTICKS
; i
++)
296 AddComboBoxTime(hwndDlg
, IDC_REPEAT_REPEAT_COMBO
, nRepeatArray
[i
]);
299 SendDlgItemMessage(hwndDlg
, IDC_REPEAT_REPEAT_COMBO
, CB_SETCURSEL
, n
, 0);
301 /* Disable the delay and repeat comboboxes if needed */
302 if (pGlobalData
->filterKeys
.iDelayMSec
== 0)
304 EnableWindow(GetDlgItem(hwndDlg
, IDC_REPEAT_DELAY_COMBO
), FALSE
);
305 EnableWindow(GetDlgItem(hwndDlg
, IDC_REPEAT_REPEAT_COMBO
), FALSE
);
308 /* Initialize the wait combobox */
309 for (n
= 0; n
< WAITTICKS
; n
++)
311 if (pGlobalData
->filterKeys
.iWaitMSec
< nWaitArray
[n
])
316 for (i
= 0; i
< WAITTICKS
; i
++)
318 AddComboBoxTime(hwndDlg
, IDC_REPEAT_WAIT_COMBO
, nWaitArray
[i
]);
321 SendDlgItemMessage(hwndDlg
, IDC_REPEAT_WAIT_COMBO
, CB_SETCURSEL
, n
, 0);
325 switch (LOWORD(wParam
))
327 case IDC_REPEAT_NOREPEAT_RADIO
:
328 pGlobalData
->filterKeys
.iDelayMSec
= 0;
329 pGlobalData
->filterKeys
.iRepeatMSec
= 0;
330 EnableWindow(GetDlgItem(hwndDlg
, IDC_REPEAT_DELAY_COMBO
), FALSE
);
331 EnableWindow(GetDlgItem(hwndDlg
, IDC_REPEAT_REPEAT_COMBO
), FALSE
);
334 case IDC_REPEAT_REPEAT_RADIO
:
335 EnableWindow(GetDlgItem(hwndDlg
, IDC_REPEAT_DELAY_COMBO
), TRUE
);
336 EnableWindow(GetDlgItem(hwndDlg
, IDC_REPEAT_REPEAT_COMBO
), TRUE
);
339 case IDC_REPEAT_DELAY_COMBO
:
340 if (HIWORD(wParam
) == CBN_SELCHANGE
)
342 i
= SendDlgItemMessage(hwndDlg
, IDC_REPEAT_DELAY_COMBO
, CB_GETCURSEL
, 0, 0);
345 pGlobalData
->filterKeys
.iDelayMSec
= nDelayArray
[i
];
350 case IDC_REPEAT_REPEAT_COMBO
:
351 if (HIWORD(wParam
) == CBN_SELCHANGE
)
353 i
= SendDlgItemMessage(hwndDlg
, IDC_REPEAT_REPEAT_COMBO
, CB_GETCURSEL
, 0, 0);
356 pGlobalData
->filterKeys
.iRepeatMSec
= nRepeatArray
[i
];
361 case IDC_REPEAT_WAIT_COMBO
:
362 if (HIWORD(wParam
) == CBN_SELCHANGE
)
364 i
= SendDlgItemMessage(hwndDlg
, IDC_REPEAT_WAIT_COMBO
, CB_GETCURSEL
, 0, 0);
367 pGlobalData
->filterKeys
.iWaitMSec
= nWaitArray
[i
];
372 case IDC_REPEAT_TEST_EDIT
:
373 switch (HIWORD(wParam
))
376 EnableFilterKeysTest(pGlobalData
);
380 DisableFilterKeysTest(pGlobalData
);
386 EndDialog(hwndDlg
, TRUE
);
390 EndDialog(hwndDlg
, FALSE
);
403 /* Property page dialog callback */
405 FilterKeysDlgProc(HWND hwndDlg
,
410 PGLOBAL_DATA pGlobalData
;
412 pGlobalData
= (PGLOBAL_DATA
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
417 pGlobalData
= (PGLOBAL_DATA
)lParam
;
418 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pGlobalData
);
420 memcpy(&pGlobalData
->oldFilterKeys
,
421 &pGlobalData
->filterKeys
,
424 CheckDlgButton(hwndDlg
,
425 IDC_FILTER_ACTIVATE_CHECK
,
426 pGlobalData
->filterKeys
.dwFlags
& FKF_HOTKEYACTIVE
? BST_CHECKED
: BST_UNCHECKED
);
428 if (pGlobalData
->filterKeys
.iBounceMSec
!= 0)
430 CheckRadioButton(hwndDlg
, IDC_FILTER_BOUNCE_RADIO
, IDC_FILTER_REPEAT_RADIO
, IDC_FILTER_BOUNCE_RADIO
);
431 EnableWindow(GetDlgItem(hwndDlg
, IDC_FILTER_BOUNCE_BUTTON
), TRUE
);
432 EnableWindow(GetDlgItem(hwndDlg
, IDC_FILTER_REPEAT_BUTTON
), FALSE
);
436 CheckRadioButton(hwndDlg
, IDC_FILTER_BOUNCE_RADIO
, IDC_FILTER_REPEAT_RADIO
, IDC_FILTER_REPEAT_RADIO
);
437 EnableWindow(GetDlgItem(hwndDlg
, IDC_FILTER_BOUNCE_BUTTON
), FALSE
);
438 EnableWindow(GetDlgItem(hwndDlg
, IDC_FILTER_REPEAT_BUTTON
), TRUE
);
441 CheckDlgButton(hwndDlg
,
442 IDC_FILTER_SOUND_CHECK
,
443 pGlobalData
->filterKeys
.dwFlags
& FKF_CLICKON
? BST_CHECKED
: BST_UNCHECKED
);
445 CheckDlgButton(hwndDlg
,
446 IDC_FILTER_STATUS_CHECK
,
447 pGlobalData
->filterKeys
.dwFlags
& FKF_INDICATOR
? BST_CHECKED
: BST_UNCHECKED
);
451 switch (LOWORD(wParam
))
453 case IDC_FILTER_ACTIVATE_CHECK
:
454 pGlobalData
->filterKeys
.dwFlags
^= FKF_HOTKEYACTIVE
;
457 case IDC_FILTER_BOUNCE_RADIO
:
458 EnableWindow(GetDlgItem(hwndDlg
, IDC_FILTER_BOUNCE_BUTTON
), TRUE
);
459 EnableWindow(GetDlgItem(hwndDlg
, IDC_FILTER_REPEAT_BUTTON
), FALSE
);
462 case IDC_FILTER_REPEAT_RADIO
:
463 EnableWindow(GetDlgItem(hwndDlg
, IDC_FILTER_BOUNCE_BUTTON
), FALSE
);
464 EnableWindow(GetDlgItem(hwndDlg
, IDC_FILTER_REPEAT_BUTTON
), TRUE
);
467 case IDC_FILTER_BOUNCE_BUTTON
:
468 DialogBoxParam(hApplet
,
469 MAKEINTRESOURCE(IDD_BOUNCEKEYSOPTIONS
),
471 (DLGPROC
)BounceKeysDlgProc
,
472 (LPARAM
)pGlobalData
);
475 case IDC_FILTER_TEST_EDIT
:
476 switch (HIWORD(wParam
))
479 EnableFilterKeysTest(pGlobalData
);
483 DisableFilterKeysTest(pGlobalData
);
488 case IDC_FILTER_SOUND_CHECK
:
489 pGlobalData
->filterKeys
.dwFlags
^= FKF_CLICKON
;
492 case IDC_FILTER_REPEAT_BUTTON
:
493 DialogBoxParam(hApplet
,
494 MAKEINTRESOURCE(IDD_REPEATKEYSOPTIONS
),
496 (DLGPROC
)RepeatKeysDlgProc
,
497 (LPARAM
)pGlobalData
);
500 case IDC_FILTER_STATUS_CHECK
:
501 pGlobalData
->filterKeys
.dwFlags
^= FKF_INDICATOR
;
506 (pGlobalData
->filterKeys
.dwFlags
!= pGlobalData
->oldFilterKeys
.dwFlags
));
510 EndDialog(hwndDlg
, FALSE
);
523 /* Property page dialog callback */
525 ToggleKeysDlgProc(HWND hwndDlg
,
530 PGLOBAL_DATA pGlobalData
;
532 pGlobalData
= (PGLOBAL_DATA
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
537 pGlobalData
= (PGLOBAL_DATA
)lParam
;
538 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pGlobalData
);
540 memcpy(&pGlobalData
->oldToggleKeys
,
541 &pGlobalData
->toggleKeys
,
544 CheckDlgButton(hwndDlg
,
545 IDC_TOGGLE_ACTIVATE_CHECK
,
546 pGlobalData
->toggleKeys
.dwFlags
& TKF_HOTKEYACTIVE
? BST_CHECKED
: BST_UNCHECKED
);
550 switch (LOWORD(wParam
))
552 case IDC_TOGGLE_ACTIVATE_CHECK
:
553 pGlobalData
->toggleKeys
.dwFlags
^= TKF_HOTKEYACTIVE
;
558 (pGlobalData
->toggleKeys
.dwFlags
!= pGlobalData
->oldToggleKeys
.dwFlags
));
562 EndDialog(hwndDlg
, FALSE
);
575 /* Property page dialog callback */
577 KeyboardPageProc(HWND hwndDlg
,
582 PGLOBAL_DATA pGlobalData
;
585 pGlobalData
= (PGLOBAL_DATA
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
590 pGlobalData
= (PGLOBAL_DATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
591 if (pGlobalData
== NULL
)
594 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pGlobalData
);
596 CheckDlgButton(hwndDlg
,
598 pGlobalData
->stickyKeys
.dwFlags
& SKF_STICKYKEYSON
? BST_CHECKED
: BST_UNCHECKED
);
600 CheckDlgButton(hwndDlg
,
602 pGlobalData
->filterKeys
.dwFlags
& FKF_FILTERKEYSON
? BST_CHECKED
: BST_UNCHECKED
);
604 CheckDlgButton(hwndDlg
,
606 pGlobalData
->toggleKeys
.dwFlags
& TKF_TOGGLEKEYSON
? BST_CHECKED
: BST_UNCHECKED
);
608 CheckDlgButton(hwndDlg
,
610 pGlobalData
->bKeyboardPref
? BST_CHECKED
: BST_UNCHECKED
);
614 switch (LOWORD(wParam
))
617 pGlobalData
->stickyKeys
.dwFlags
^= SKF_STICKYKEYSON
;
618 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
621 case IDC_STICKY_BUTTON
:
622 if (DialogBoxParam(hApplet
,
623 MAKEINTRESOURCE(IDD_STICKYKEYSOPTIONS
),
625 (DLGPROC
)StickyKeysDlgProc
,
626 (LPARAM
)pGlobalData
))
627 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
631 pGlobalData
->filterKeys
.dwFlags
^= FKF_FILTERKEYSON
;
632 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
635 case IDC_FILTER_BUTTON
:
636 if (DialogBoxParam(hApplet
,
637 MAKEINTRESOURCE(IDD_FILTERKEYSOPTIONS
),
639 (DLGPROC
)FilterKeysDlgProc
,
640 (LPARAM
)pGlobalData
))
641 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
645 pGlobalData
->toggleKeys
.dwFlags
^= TKF_TOGGLEKEYSON
;
646 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
649 case IDC_TOGGLE_BUTTON
:
650 if (DialogBoxParam(hApplet
,
651 MAKEINTRESOURCE(IDD_TOGGLEKEYSOPTIONS
),
653 (DLGPROC
)ToggleKeysDlgProc
,
654 (LPARAM
)pGlobalData
))
655 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
658 case IDC_KEYBOARD_EXTRA
:
659 pGlobalData
->bKeyboardPref
= !pGlobalData
->bKeyboardPref
;
660 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
669 lppsn
= (LPPSHNOTIFY
)lParam
;
670 if (lppsn
->hdr
.code
== PSN_APPLY
)
672 SystemParametersInfo(SPI_SETSTICKYKEYS
,
674 &pGlobalData
->stickyKeys
,
675 SPIF_UPDATEINIFILE
| SPIF_SENDCHANGE
/*0*/);
677 SystemParametersInfo(SPI_SETFILTERKEYS
,
679 &pGlobalData
->filterKeys
,
680 SPIF_UPDATEINIFILE
| SPIF_SENDCHANGE
/*0*/);
682 SystemParametersInfo(SPI_SETTOGGLEKEYS
,
684 &pGlobalData
->toggleKeys
,
685 SPIF_UPDATEINIFILE
| SPIF_SENDCHANGE
/*0*/);
687 SystemParametersInfo(SPI_SETKEYBOARDPREF
,
688 pGlobalData
->bKeyboardPref
,
690 SPIF_UPDATEINIFILE
| SPIF_SENDCHANGE
/*0*/);