3 * PROJECT: ReactOS Accessibility Control Panel
4 * LICENSE: GPL - See COPYING in the top level directory
5 * FILE: dll/cpl/access/keyboard.c
6 * PURPOSE: Keyboard-related accessibility settings
7 * COPYRIGHT: Copyright 2004 Johannes Anderwald (j_anderw@sbox.tugraz.at)
8 * Copyright 2007 Eric Kohl
22 static INT nBounceArray
[BOUNCETICKS
] = {500, 700, 1000, 1500, 2000};
25 static INT nDelayArray
[DELAYTICKS
] = {300, 700, 1000, 1500, 2000};
28 static INT nRepeatArray
[REPEATTICKS
] = {300, 500, 700, 1000, 1500, 2000};
31 static INT nWaitArray
[WAITTICKS
] = {0, 300, 500, 700, 1000, 1500, 2000, 5000, 10000, 20000};
35 EnableFilterKeysTest(PGLOBAL_DATA pGlobalData
)
37 pGlobalData
->filterKeys
.dwFlags
|= FKF_FILTERKEYSON
;
38 pGlobalData
->filterKeys
.dwFlags
&= ~FKF_INDICATOR
;
40 SystemParametersInfo(SPI_SETFILTERKEYS
,
42 &pGlobalData
->filterKeys
,
48 DisableFilterKeysTest(PGLOBAL_DATA pGlobalData
)
50 if (pGlobalData
->oldFilterKeys
.dwFlags
& FKF_FILTERKEYSON
)
52 pGlobalData
->filterKeys
.dwFlags
|= FKF_FILTERKEYSON
;
56 pGlobalData
->filterKeys
.dwFlags
&= ~FKF_FILTERKEYSON
;
59 if (pGlobalData
->oldFilterKeys
.dwFlags
& FKF_INDICATOR
)
61 pGlobalData
->filterKeys
.dwFlags
|= FKF_INDICATOR
;
65 pGlobalData
->filterKeys
.dwFlags
&= ~FKF_INDICATOR
;
68 SystemParametersInfo(SPI_SETFILTERKEYS
,
70 &pGlobalData
->filterKeys
,
75 /* Property page dialog callback */
77 StickyKeysDlgProc(HWND hwndDlg
,
82 PGLOBAL_DATA pGlobalData
;
84 pGlobalData
= (PGLOBAL_DATA
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
89 pGlobalData
= (PGLOBAL_DATA
)lParam
;
90 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pGlobalData
);
92 memcpy(&pGlobalData
->oldStickyKeys
,
93 &pGlobalData
->stickyKeys
,
96 CheckDlgButton(hwndDlg
,
97 IDC_STICKY_ACTIVATE_CHECK
,
98 pGlobalData
->stickyKeys
.dwFlags
& SKF_HOTKEYACTIVE
? BST_CHECKED
: BST_UNCHECKED
);
100 CheckDlgButton(hwndDlg
,
101 IDC_STICKY_LOCK_CHECK
,
102 pGlobalData
->stickyKeys
.dwFlags
& SKF_TRISTATE
? BST_CHECKED
: BST_UNCHECKED
);
104 CheckDlgButton(hwndDlg
,
105 IDC_STICKY_UNLOCK_CHECK
,
106 pGlobalData
->stickyKeys
.dwFlags
& SKF_TWOKEYSOFF
? BST_CHECKED
: BST_UNCHECKED
);
108 CheckDlgButton(hwndDlg
,
109 IDC_STICKY_SOUND_CHECK
,
110 pGlobalData
->stickyKeys
.dwFlags
& SKF_AUDIBLEFEEDBACK
? BST_CHECKED
: BST_UNCHECKED
);
112 CheckDlgButton(hwndDlg
,
113 IDC_STICKY_STATUS_CHECK
,
114 pGlobalData
->stickyKeys
.dwFlags
& SKF_INDICATOR
? BST_CHECKED
: BST_UNCHECKED
);
118 switch (LOWORD(wParam
))
120 case IDC_STICKY_ACTIVATE_CHECK
:
121 pGlobalData
->stickyKeys
.dwFlags
^= SKF_HOTKEYACTIVE
;
124 case IDC_STICKY_LOCK_CHECK
:
125 pGlobalData
->stickyKeys
.dwFlags
^= SKF_TRISTATE
;
128 case IDC_STICKY_UNLOCK_CHECK
:
129 pGlobalData
->stickyKeys
.dwFlags
^= SKF_TWOKEYSOFF
;
132 case IDC_STICKY_SOUND_CHECK
:
133 pGlobalData
->stickyKeys
.dwFlags
^= SKF_AUDIBLEFEEDBACK
;
136 case IDC_STICKY_STATUS_CHECK
:
137 pGlobalData
->stickyKeys
.dwFlags
^= SKF_INDICATOR
;
142 (pGlobalData
->stickyKeys
.dwFlags
!= pGlobalData
->oldStickyKeys
.dwFlags
));
146 EndDialog(hwndDlg
, FALSE
);
160 AddComboBoxTime(HWND hwnd
, INT nId
, INT nTimeMs
)
165 if (LoadString(hApplet
, IDS_SECONDS
, szSeconds
, 20) == 0)
166 lstrcpy(szSeconds
, L
"Seconds");
168 _stprintf(szBuffer
, _T("%d.%d %s"),
169 nTimeMs
/ 1000, (nTimeMs
% 1000) / 100,
172 SendDlgItemMessage(hwnd
, nId
, CB_ADDSTRING
, 0, (LPARAM
)szBuffer
);
177 BounceKeysDlgProc(HWND hwndDlg
,
182 PGLOBAL_DATA pGlobalData
;
185 pGlobalData
= (PGLOBAL_DATA
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
190 pGlobalData
= (PGLOBAL_DATA
)lParam
;
191 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pGlobalData
);
193 /* Determine the current bounce time */
194 if (pGlobalData
->filterKeys
.iBounceMSec
== 0)
195 pGlobalData
->filterKeys
.iBounceMSec
= nBounceArray
[0];
197 for (n
= 0; n
< BOUNCETICKS
; n
++)
199 if (pGlobalData
->filterKeys
.iBounceMSec
< nBounceArray
[n
])
204 for (i
= 0; i
< BOUNCETICKS
; i
++)
206 AddComboBoxTime(hwndDlg
, IDC_BOUNCE_TIME_COMBO
, nBounceArray
[i
]);
209 SendDlgItemMessage(hwndDlg
, IDC_BOUNCE_TIME_COMBO
, CB_SETCURSEL
, n
, 0);
213 switch (LOWORD(wParam
))
215 case IDC_BOUNCE_TIME_COMBO
:
216 if (HIWORD(wParam
) == CBN_SELCHANGE
)
218 i
= SendDlgItemMessage(hwndDlg
, IDC_BOUNCE_TIME_COMBO
, CB_GETCURSEL
, 0, 0);
221 pGlobalData
->filterKeys
.iBounceMSec
= nBounceArray
[i
];
226 case IDC_BOUNCE_TEST_EDIT
:
227 switch (HIWORD(wParam
))
230 EnableFilterKeysTest(pGlobalData
);
234 DisableFilterKeysTest(pGlobalData
);
240 EndDialog(hwndDlg
, TRUE
);
244 EndDialog(hwndDlg
, FALSE
);
258 RepeatKeysDlgProc(HWND hwndDlg
,
263 PGLOBAL_DATA pGlobalData
;
266 pGlobalData
= (PGLOBAL_DATA
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
271 pGlobalData
= (PGLOBAL_DATA
)lParam
;
272 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pGlobalData
);
274 CheckRadioButton(hwndDlg
,
275 IDC_REPEAT_NOREPEAT_RADIO
,
276 IDC_REPEAT_REPEAT_RADIO
,
277 (pGlobalData
->filterKeys
.iDelayMSec
== 0) ? IDC_REPEAT_NOREPEAT_RADIO
: IDC_REPEAT_REPEAT_RADIO
);
279 /* Initialize the delay combobox */
280 for (n
= 0; n
< DELAYTICKS
; n
++)
282 if (pGlobalData
->filterKeys
.iDelayMSec
< nDelayArray
[n
])
287 for (i
= 0; i
< DELAYTICKS
; i
++)
289 AddComboBoxTime(hwndDlg
, IDC_REPEAT_DELAY_COMBO
, nDelayArray
[i
]);
292 SendDlgItemMessage(hwndDlg
, IDC_REPEAT_DELAY_COMBO
, CB_SETCURSEL
, n
, 0);
294 /* Initialize the repeat combobox */
295 for (n
= 0; n
< REPEATTICKS
; n
++)
297 if (pGlobalData
->filterKeys
.iRepeatMSec
< nRepeatArray
[n
])
302 for (i
= 0; i
< REPEATTICKS
; i
++)
304 AddComboBoxTime(hwndDlg
, IDC_REPEAT_REPEAT_COMBO
, nRepeatArray
[i
]);
307 SendDlgItemMessage(hwndDlg
, IDC_REPEAT_REPEAT_COMBO
, CB_SETCURSEL
, n
, 0);
309 /* Disable the delay and repeat comboboxes if needed */
310 if (pGlobalData
->filterKeys
.iDelayMSec
== 0)
312 EnableWindow(GetDlgItem(hwndDlg
, IDC_REPEAT_DELAY_COMBO
), FALSE
);
313 EnableWindow(GetDlgItem(hwndDlg
, IDC_REPEAT_REPEAT_COMBO
), FALSE
);
316 /* Initialize the wait combobox */
317 for (n
= 0; n
< WAITTICKS
; n
++)
319 if (pGlobalData
->filterKeys
.iWaitMSec
< nWaitArray
[n
])
324 for (i
= 0; i
< WAITTICKS
; i
++)
326 AddComboBoxTime(hwndDlg
, IDC_REPEAT_WAIT_COMBO
, nWaitArray
[i
]);
329 SendDlgItemMessage(hwndDlg
, IDC_REPEAT_WAIT_COMBO
, CB_SETCURSEL
, n
, 0);
333 switch (LOWORD(wParam
))
335 case IDC_REPEAT_NOREPEAT_RADIO
:
336 pGlobalData
->filterKeys
.iDelayMSec
= 0;
337 pGlobalData
->filterKeys
.iRepeatMSec
= 0;
338 EnableWindow(GetDlgItem(hwndDlg
, IDC_REPEAT_DELAY_COMBO
), FALSE
);
339 EnableWindow(GetDlgItem(hwndDlg
, IDC_REPEAT_REPEAT_COMBO
), FALSE
);
342 case IDC_REPEAT_REPEAT_RADIO
:
343 EnableWindow(GetDlgItem(hwndDlg
, IDC_REPEAT_DELAY_COMBO
), TRUE
);
344 EnableWindow(GetDlgItem(hwndDlg
, IDC_REPEAT_REPEAT_COMBO
), TRUE
);
347 case IDC_REPEAT_DELAY_COMBO
:
348 if (HIWORD(wParam
) == CBN_SELCHANGE
)
350 i
= SendDlgItemMessage(hwndDlg
, IDC_REPEAT_DELAY_COMBO
, CB_GETCURSEL
, 0, 0);
353 pGlobalData
->filterKeys
.iDelayMSec
= nDelayArray
[i
];
358 case IDC_REPEAT_REPEAT_COMBO
:
359 if (HIWORD(wParam
) == CBN_SELCHANGE
)
361 i
= SendDlgItemMessage(hwndDlg
, IDC_REPEAT_REPEAT_COMBO
, CB_GETCURSEL
, 0, 0);
364 pGlobalData
->filterKeys
.iRepeatMSec
= nRepeatArray
[i
];
369 case IDC_REPEAT_WAIT_COMBO
:
370 if (HIWORD(wParam
) == CBN_SELCHANGE
)
372 i
= SendDlgItemMessage(hwndDlg
, IDC_REPEAT_WAIT_COMBO
, CB_GETCURSEL
, 0, 0);
375 pGlobalData
->filterKeys
.iWaitMSec
= nWaitArray
[i
];
380 case IDC_REPEAT_TEST_EDIT
:
381 switch (HIWORD(wParam
))
384 EnableFilterKeysTest(pGlobalData
);
388 DisableFilterKeysTest(pGlobalData
);
394 EndDialog(hwndDlg
, TRUE
);
398 EndDialog(hwndDlg
, FALSE
);
411 /* Property page dialog callback */
413 FilterKeysDlgProc(HWND hwndDlg
,
418 PGLOBAL_DATA pGlobalData
;
420 pGlobalData
= (PGLOBAL_DATA
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
425 pGlobalData
= (PGLOBAL_DATA
)lParam
;
426 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pGlobalData
);
428 memcpy(&pGlobalData
->oldFilterKeys
,
429 &pGlobalData
->filterKeys
,
432 CheckDlgButton(hwndDlg
,
433 IDC_FILTER_ACTIVATE_CHECK
,
434 pGlobalData
->filterKeys
.dwFlags
& FKF_HOTKEYACTIVE
? BST_CHECKED
: BST_UNCHECKED
);
436 if (pGlobalData
->filterKeys
.iBounceMSec
!= 0)
438 CheckRadioButton(hwndDlg
, IDC_FILTER_BOUNCE_RADIO
, IDC_FILTER_REPEAT_RADIO
, IDC_FILTER_BOUNCE_RADIO
);
439 EnableWindow(GetDlgItem(hwndDlg
, IDC_FILTER_BOUNCE_BUTTON
), TRUE
);
440 EnableWindow(GetDlgItem(hwndDlg
, IDC_FILTER_REPEAT_BUTTON
), FALSE
);
444 CheckRadioButton(hwndDlg
, IDC_FILTER_BOUNCE_RADIO
, IDC_FILTER_REPEAT_RADIO
, IDC_FILTER_REPEAT_RADIO
);
445 EnableWindow(GetDlgItem(hwndDlg
, IDC_FILTER_BOUNCE_BUTTON
), FALSE
);
446 EnableWindow(GetDlgItem(hwndDlg
, IDC_FILTER_REPEAT_BUTTON
), TRUE
);
449 CheckDlgButton(hwndDlg
,
450 IDC_FILTER_SOUND_CHECK
,
451 pGlobalData
->filterKeys
.dwFlags
& FKF_CLICKON
? BST_CHECKED
: BST_UNCHECKED
);
453 CheckDlgButton(hwndDlg
,
454 IDC_FILTER_STATUS_CHECK
,
455 pGlobalData
->filterKeys
.dwFlags
& FKF_INDICATOR
? BST_CHECKED
: BST_UNCHECKED
);
459 switch (LOWORD(wParam
))
461 case IDC_FILTER_ACTIVATE_CHECK
:
462 pGlobalData
->filterKeys
.dwFlags
^= FKF_HOTKEYACTIVE
;
465 case IDC_FILTER_BOUNCE_RADIO
:
466 EnableWindow(GetDlgItem(hwndDlg
, IDC_FILTER_BOUNCE_BUTTON
), TRUE
);
467 EnableWindow(GetDlgItem(hwndDlg
, IDC_FILTER_REPEAT_BUTTON
), FALSE
);
470 case IDC_FILTER_REPEAT_RADIO
:
471 EnableWindow(GetDlgItem(hwndDlg
, IDC_FILTER_BOUNCE_BUTTON
), FALSE
);
472 EnableWindow(GetDlgItem(hwndDlg
, IDC_FILTER_REPEAT_BUTTON
), TRUE
);
475 case IDC_FILTER_BOUNCE_BUTTON
:
476 DialogBoxParam(hApplet
,
477 MAKEINTRESOURCE(IDD_BOUNCEKEYSOPTIONS
),
479 (DLGPROC
)BounceKeysDlgProc
,
480 (LPARAM
)pGlobalData
);
483 case IDC_FILTER_TEST_EDIT
:
484 switch (HIWORD(wParam
))
487 EnableFilterKeysTest(pGlobalData
);
491 DisableFilterKeysTest(pGlobalData
);
496 case IDC_FILTER_SOUND_CHECK
:
497 pGlobalData
->filterKeys
.dwFlags
^= FKF_CLICKON
;
500 case IDC_FILTER_REPEAT_BUTTON
:
501 DialogBoxParam(hApplet
,
502 MAKEINTRESOURCE(IDD_REPEATKEYSOPTIONS
),
504 (DLGPROC
)RepeatKeysDlgProc
,
505 (LPARAM
)pGlobalData
);
508 case IDC_FILTER_STATUS_CHECK
:
509 pGlobalData
->filterKeys
.dwFlags
^= FKF_INDICATOR
;
514 (pGlobalData
->filterKeys
.dwFlags
!= pGlobalData
->oldFilterKeys
.dwFlags
));
518 EndDialog(hwndDlg
, FALSE
);
531 /* Property page dialog callback */
533 ToggleKeysDlgProc(HWND hwndDlg
,
538 PGLOBAL_DATA pGlobalData
;
540 pGlobalData
= (PGLOBAL_DATA
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
545 pGlobalData
= (PGLOBAL_DATA
)lParam
;
546 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pGlobalData
);
548 memcpy(&pGlobalData
->oldToggleKeys
,
549 &pGlobalData
->toggleKeys
,
552 CheckDlgButton(hwndDlg
,
553 IDC_TOGGLE_ACTIVATE_CHECK
,
554 pGlobalData
->toggleKeys
.dwFlags
& TKF_HOTKEYACTIVE
? BST_CHECKED
: BST_UNCHECKED
);
558 switch (LOWORD(wParam
))
560 case IDC_TOGGLE_ACTIVATE_CHECK
:
561 pGlobalData
->toggleKeys
.dwFlags
^= TKF_HOTKEYACTIVE
;
566 (pGlobalData
->toggleKeys
.dwFlags
!= pGlobalData
->oldToggleKeys
.dwFlags
));
570 EndDialog(hwndDlg
, FALSE
);
583 /* Property page dialog callback */
585 KeyboardPageProc(HWND hwndDlg
,
590 PGLOBAL_DATA pGlobalData
;
593 pGlobalData
= (PGLOBAL_DATA
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
598 pGlobalData
= (PGLOBAL_DATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
599 if (pGlobalData
== NULL
)
602 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pGlobalData
);
604 CheckDlgButton(hwndDlg
,
606 pGlobalData
->stickyKeys
.dwFlags
& SKF_STICKYKEYSON
? BST_CHECKED
: BST_UNCHECKED
);
608 CheckDlgButton(hwndDlg
,
610 pGlobalData
->filterKeys
.dwFlags
& FKF_FILTERKEYSON
? BST_CHECKED
: BST_UNCHECKED
);
612 CheckDlgButton(hwndDlg
,
614 pGlobalData
->toggleKeys
.dwFlags
& TKF_TOGGLEKEYSON
? BST_CHECKED
: BST_UNCHECKED
);
616 CheckDlgButton(hwndDlg
,
618 pGlobalData
->bKeyboardPref
? BST_CHECKED
: BST_UNCHECKED
);
622 switch (LOWORD(wParam
))
625 pGlobalData
->stickyKeys
.dwFlags
^= SKF_STICKYKEYSON
;
626 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
629 case IDC_STICKY_BUTTON
:
630 if (DialogBoxParam(hApplet
,
631 MAKEINTRESOURCE(IDD_STICKYKEYSOPTIONS
),
633 (DLGPROC
)StickyKeysDlgProc
,
634 (LPARAM
)pGlobalData
))
635 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
639 pGlobalData
->filterKeys
.dwFlags
^= FKF_FILTERKEYSON
;
640 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
643 case IDC_FILTER_BUTTON
:
644 if (DialogBoxParam(hApplet
,
645 MAKEINTRESOURCE(IDD_FILTERKEYSOPTIONS
),
647 (DLGPROC
)FilterKeysDlgProc
,
648 (LPARAM
)pGlobalData
))
649 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
653 pGlobalData
->toggleKeys
.dwFlags
^= TKF_TOGGLEKEYSON
;
654 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
657 case IDC_TOGGLE_BUTTON
:
658 if (DialogBoxParam(hApplet
,
659 MAKEINTRESOURCE(IDD_TOGGLEKEYSOPTIONS
),
661 (DLGPROC
)ToggleKeysDlgProc
,
662 (LPARAM
)pGlobalData
))
663 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
666 case IDC_KEYBOARD_EXTRA
:
667 pGlobalData
->bKeyboardPref
= !pGlobalData
->bKeyboardPref
;
668 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
677 lppsn
= (LPPSHNOTIFY
)lParam
;
678 if (lppsn
->hdr
.code
== PSN_APPLY
)
680 SystemParametersInfo(SPI_SETSTICKYKEYS
,
682 &pGlobalData
->stickyKeys
,
683 SPIF_UPDATEINIFILE
| SPIF_SENDCHANGE
/*0*/);
685 SystemParametersInfo(SPI_SETFILTERKEYS
,
687 &pGlobalData
->filterKeys
,
688 SPIF_UPDATEINIFILE
| SPIF_SENDCHANGE
/*0*/);
690 SystemParametersInfo(SPI_SETTOGGLEKEYS
,
692 &pGlobalData
->toggleKeys
,
693 SPIF_UPDATEINIFILE
| SPIF_SENDCHANGE
/*0*/);
695 SystemParametersInfo(SPI_SETKEYBOARDPREF
,
696 pGlobalData
->bKeyboardPref
,
698 SPIF_UPDATEINIFILE
| SPIF_SENDCHANGE
/*0*/);