reactos/dll/cpl/access/keyboard.c
2017-11-03 13:57:44 +01:00

698 lines
23 KiB
C

/*
* PROJECT: ReactOS Accessibility Control Panel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: dll/cpl/access/keyboard.c
* PURPOSE: Keyboard-related accessibility settings
* COPYRIGHT: Copyright 2004 Johannes Anderwald (johannes.anderwald@reactos.org)
* Copyright 2007 Eric Kohl
*/
#include "access.h"
#define BOUNCETICKS 5
static UINT nBounceArray[BOUNCETICKS] = {500, 700, 1000, 1500, 2000};
#define DELAYTICKS 5
static UINT nDelayArray[DELAYTICKS] = {300, 700, 1000, 1500, 2000};
#define REPEATTICKS 6
static UINT nRepeatArray[REPEATTICKS] = {300, 500, 700, 1000, 1500, 2000};
#define WAITTICKS 10
static UINT nWaitArray[WAITTICKS] = {0, 300, 500, 700, 1000, 1500, 2000, 5000, 10000, 20000};
static VOID
EnableFilterKeysTest(PGLOBAL_DATA pGlobalData)
{
pGlobalData->filterKeys.dwFlags |= FKF_FILTERKEYSON;
pGlobalData->filterKeys.dwFlags &= ~FKF_INDICATOR;
SystemParametersInfo(SPI_SETFILTERKEYS,
sizeof(FILTERKEYS),
&pGlobalData->filterKeys,
0);
}
static VOID
DisableFilterKeysTest(PGLOBAL_DATA pGlobalData)
{
if (pGlobalData->oldFilterKeys.dwFlags & FKF_FILTERKEYSON)
{
pGlobalData->filterKeys.dwFlags |= FKF_FILTERKEYSON;
}
else
{
pGlobalData->filterKeys.dwFlags &= ~FKF_FILTERKEYSON;
}
if (pGlobalData->oldFilterKeys.dwFlags & FKF_INDICATOR)
{
pGlobalData->filterKeys.dwFlags |= FKF_INDICATOR;
}
else
{
pGlobalData->filterKeys.dwFlags &= ~FKF_INDICATOR;
}
SystemParametersInfo(SPI_SETFILTERKEYS,
sizeof(FILTERKEYS),
&pGlobalData->filterKeys,
0);
}
/* Property page dialog callback */
INT_PTR CALLBACK
StickyKeysDlgProc(HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
PGLOBAL_DATA pGlobalData;
pGlobalData = (PGLOBAL_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
switch (uMsg)
{
case WM_INITDIALOG:
pGlobalData = (PGLOBAL_DATA)lParam;
SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pGlobalData);
memcpy(&pGlobalData->oldStickyKeys,
&pGlobalData->stickyKeys,
sizeof(STICKYKEYS));
CheckDlgButton(hwndDlg,
IDC_STICKY_ACTIVATE_CHECK,
pGlobalData->stickyKeys.dwFlags & SKF_HOTKEYACTIVE ? BST_CHECKED : BST_UNCHECKED);
CheckDlgButton(hwndDlg,
IDC_STICKY_LOCK_CHECK,
pGlobalData->stickyKeys.dwFlags & SKF_TRISTATE ? BST_CHECKED : BST_UNCHECKED);
CheckDlgButton(hwndDlg,
IDC_STICKY_UNLOCK_CHECK,
pGlobalData->stickyKeys.dwFlags & SKF_TWOKEYSOFF ? BST_CHECKED : BST_UNCHECKED);
CheckDlgButton(hwndDlg,
IDC_STICKY_SOUND_CHECK,
pGlobalData->stickyKeys.dwFlags & SKF_AUDIBLEFEEDBACK ? BST_CHECKED : BST_UNCHECKED);
CheckDlgButton(hwndDlg,
IDC_STICKY_STATUS_CHECK,
pGlobalData->stickyKeys.dwFlags & SKF_INDICATOR ? BST_CHECKED : BST_UNCHECKED);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_STICKY_ACTIVATE_CHECK:
pGlobalData->stickyKeys.dwFlags ^= SKF_HOTKEYACTIVE;
break;
case IDC_STICKY_LOCK_CHECK:
pGlobalData->stickyKeys.dwFlags ^= SKF_TRISTATE;
break;
case IDC_STICKY_UNLOCK_CHECK:
pGlobalData->stickyKeys.dwFlags ^= SKF_TWOKEYSOFF;
break;
case IDC_STICKY_SOUND_CHECK:
pGlobalData->stickyKeys.dwFlags ^= SKF_AUDIBLEFEEDBACK;
break;
case IDC_STICKY_STATUS_CHECK:
pGlobalData->stickyKeys.dwFlags ^= SKF_INDICATOR;
break;
case IDOK:
EndDialog(hwndDlg,
(pGlobalData->stickyKeys.dwFlags != pGlobalData->oldStickyKeys.dwFlags));
break;
case IDCANCEL:
EndDialog(hwndDlg, FALSE);
break;
default:
break;
}
break;
}
return FALSE;
}
static VOID
AddComboBoxTime(HWND hwnd, INT nId, INT nTimeMs)
{
TCHAR szBuffer[32];
TCHAR szSeconds[20];
if (LoadString(hApplet, IDS_SECONDS, szSeconds, 20) == 0)
lstrcpy(szSeconds, L"Seconds");
_stprintf(szBuffer, _T("%d.%d %s"),
nTimeMs / 1000, (nTimeMs % 1000) / 100,
szSeconds);
SendDlgItemMessage(hwnd, nId, CB_ADDSTRING, 0, (LPARAM)szBuffer);
}
INT_PTR CALLBACK
BounceKeysDlgProc(HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
PGLOBAL_DATA pGlobalData;
INT i, n;
pGlobalData = (PGLOBAL_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
switch (uMsg)
{
case WM_INITDIALOG:
pGlobalData = (PGLOBAL_DATA)lParam;
SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pGlobalData);
/* Determine the current bounce time */
if (pGlobalData->filterKeys.iBounceMSec == 0)
pGlobalData->filterKeys.iBounceMSec = nBounceArray[0];
for (n = 0; n < BOUNCETICKS; n++)
{
if (pGlobalData->filterKeys.iBounceMSec < nBounceArray[n])
break;
}
n--;
for (i = 0; i < BOUNCETICKS; i++)
{
AddComboBoxTime(hwndDlg, IDC_BOUNCE_TIME_COMBO, nBounceArray[i]);
}
SendDlgItemMessage(hwndDlg, IDC_BOUNCE_TIME_COMBO, CB_SETCURSEL, n, 0);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_BOUNCE_TIME_COMBO:
if (HIWORD(wParam) == CBN_SELCHANGE)
{
i = SendDlgItemMessage(hwndDlg, IDC_BOUNCE_TIME_COMBO, CB_GETCURSEL, 0, 0);
if (i != CB_ERR)
{
pGlobalData->filterKeys.iBounceMSec = nBounceArray[i];
}
}
break;
case IDC_BOUNCE_TEST_EDIT:
switch (HIWORD(wParam))
{
case EN_SETFOCUS:
EnableFilterKeysTest(pGlobalData);
break;
case EN_KILLFOCUS:
DisableFilterKeysTest(pGlobalData);
break;
}
break;
case IDOK:
EndDialog(hwndDlg, TRUE);
break;
case IDCANCEL:
EndDialog(hwndDlg, FALSE);
break;
default:
break;
}
break;
}
return FALSE;
}
INT_PTR CALLBACK
RepeatKeysDlgProc(HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
PGLOBAL_DATA pGlobalData;
INT i, n;
pGlobalData = (PGLOBAL_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
switch (uMsg)
{
case WM_INITDIALOG:
pGlobalData = (PGLOBAL_DATA)lParam;
SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pGlobalData);
CheckRadioButton(hwndDlg,
IDC_REPEAT_NOREPEAT_RADIO,
IDC_REPEAT_REPEAT_RADIO,
(pGlobalData->filterKeys.iDelayMSec == 0) ? IDC_REPEAT_NOREPEAT_RADIO : IDC_REPEAT_REPEAT_RADIO);
/* Initialize the delay combobox */
for (n = 0; n < DELAYTICKS; n++)
{
if (pGlobalData->filterKeys.iDelayMSec < nDelayArray[n])
break;
}
n--;
for (i = 0; i < DELAYTICKS; i++)
{
AddComboBoxTime(hwndDlg, IDC_REPEAT_DELAY_COMBO, nDelayArray[i]);
}
SendDlgItemMessage(hwndDlg, IDC_REPEAT_DELAY_COMBO, CB_SETCURSEL, n, 0);
/* Initialize the repeat combobox */
for (n = 0; n < REPEATTICKS; n++)
{
if (pGlobalData->filterKeys.iRepeatMSec < nRepeatArray[n])
break;
}
n--;
for (i = 0; i < REPEATTICKS; i++)
{
AddComboBoxTime(hwndDlg, IDC_REPEAT_REPEAT_COMBO, nRepeatArray[i]);
}
SendDlgItemMessage(hwndDlg, IDC_REPEAT_REPEAT_COMBO, CB_SETCURSEL, n, 0);
/* Disable the delay and repeat comboboxes if needed */
if (pGlobalData->filterKeys.iDelayMSec == 0)
{
EnableWindow(GetDlgItem(hwndDlg, IDC_REPEAT_DELAY_COMBO), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_REPEAT_REPEAT_COMBO), FALSE);
}
/* Initialize the wait combobox */
for (n = 0; n < WAITTICKS; n++)
{
if (pGlobalData->filterKeys.iWaitMSec < nWaitArray[n])
break;
}
n--;
for (i = 0; i < WAITTICKS; i++)
{
AddComboBoxTime(hwndDlg, IDC_REPEAT_WAIT_COMBO, nWaitArray[i]);
}
SendDlgItemMessage(hwndDlg, IDC_REPEAT_WAIT_COMBO, CB_SETCURSEL, n, 0);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_REPEAT_NOREPEAT_RADIO:
pGlobalData->filterKeys.iDelayMSec = 0;
pGlobalData->filterKeys.iRepeatMSec = 0;
EnableWindow(GetDlgItem(hwndDlg, IDC_REPEAT_DELAY_COMBO), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_REPEAT_REPEAT_COMBO), FALSE);
break;
case IDC_REPEAT_REPEAT_RADIO:
EnableWindow(GetDlgItem(hwndDlg, IDC_REPEAT_DELAY_COMBO), TRUE);
EnableWindow(GetDlgItem(hwndDlg, IDC_REPEAT_REPEAT_COMBO), TRUE);
break;
case IDC_REPEAT_DELAY_COMBO:
if (HIWORD(wParam) == CBN_SELCHANGE)
{
i = SendDlgItemMessage(hwndDlg, IDC_REPEAT_DELAY_COMBO, CB_GETCURSEL, 0, 0);
if (i != CB_ERR)
{
pGlobalData->filterKeys.iDelayMSec = nDelayArray[i];
}
}
break;
case IDC_REPEAT_REPEAT_COMBO:
if (HIWORD(wParam) == CBN_SELCHANGE)
{
i = SendDlgItemMessage(hwndDlg, IDC_REPEAT_REPEAT_COMBO, CB_GETCURSEL, 0, 0);
if (i != CB_ERR)
{
pGlobalData->filterKeys.iRepeatMSec = nRepeatArray[i];
}
}
break;
case IDC_REPEAT_WAIT_COMBO:
if (HIWORD(wParam) == CBN_SELCHANGE)
{
i = SendDlgItemMessage(hwndDlg, IDC_REPEAT_WAIT_COMBO, CB_GETCURSEL, 0, 0);
if (i != CB_ERR)
{
pGlobalData->filterKeys.iWaitMSec = nWaitArray[i];
}
}
break;
case IDC_REPEAT_TEST_EDIT:
switch (HIWORD(wParam))
{
case EN_SETFOCUS:
EnableFilterKeysTest(pGlobalData);
break;
case EN_KILLFOCUS:
DisableFilterKeysTest(pGlobalData);
break;
}
break;
case IDOK:
EndDialog(hwndDlg, TRUE);
break;
case IDCANCEL:
EndDialog(hwndDlg, FALSE);
break;
default:
break;
}
break;
}
return FALSE;
}
/* Property page dialog callback */
INT_PTR CALLBACK
FilterKeysDlgProc(HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
PGLOBAL_DATA pGlobalData;
pGlobalData = (PGLOBAL_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
switch (uMsg)
{
case WM_INITDIALOG:
pGlobalData = (PGLOBAL_DATA)lParam;
SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pGlobalData);
memcpy(&pGlobalData->oldFilterKeys,
&pGlobalData->filterKeys,
sizeof(FILTERKEYS));
CheckDlgButton(hwndDlg,
IDC_FILTER_ACTIVATE_CHECK,
pGlobalData->filterKeys.dwFlags & FKF_HOTKEYACTIVE ? BST_CHECKED : BST_UNCHECKED);
if (pGlobalData->filterKeys.iBounceMSec != 0)
{
CheckRadioButton(hwndDlg, IDC_FILTER_BOUNCE_RADIO, IDC_FILTER_REPEAT_RADIO, IDC_FILTER_BOUNCE_RADIO);
EnableWindow(GetDlgItem(hwndDlg, IDC_FILTER_BOUNCE_BUTTON), TRUE);
EnableWindow(GetDlgItem(hwndDlg, IDC_FILTER_REPEAT_BUTTON), FALSE);
}
else
{
CheckRadioButton(hwndDlg, IDC_FILTER_BOUNCE_RADIO, IDC_FILTER_REPEAT_RADIO, IDC_FILTER_REPEAT_RADIO);
EnableWindow(GetDlgItem(hwndDlg, IDC_FILTER_BOUNCE_BUTTON), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_FILTER_REPEAT_BUTTON), TRUE);
}
CheckDlgButton(hwndDlg,
IDC_FILTER_SOUND_CHECK,
pGlobalData->filterKeys.dwFlags & FKF_CLICKON ? BST_CHECKED : BST_UNCHECKED);
CheckDlgButton(hwndDlg,
IDC_FILTER_STATUS_CHECK,
pGlobalData->filterKeys.dwFlags & FKF_INDICATOR ? BST_CHECKED : BST_UNCHECKED);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_FILTER_ACTIVATE_CHECK:
pGlobalData->filterKeys.dwFlags ^= FKF_HOTKEYACTIVE;
break;
case IDC_FILTER_BOUNCE_RADIO:
EnableWindow(GetDlgItem(hwndDlg, IDC_FILTER_BOUNCE_BUTTON), TRUE);
EnableWindow(GetDlgItem(hwndDlg, IDC_FILTER_REPEAT_BUTTON), FALSE);
break;
case IDC_FILTER_REPEAT_RADIO:
EnableWindow(GetDlgItem(hwndDlg, IDC_FILTER_BOUNCE_BUTTON), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_FILTER_REPEAT_BUTTON), TRUE);
break;
case IDC_FILTER_BOUNCE_BUTTON:
DialogBoxParam(hApplet,
MAKEINTRESOURCE(IDD_BOUNCEKEYSOPTIONS),
hwndDlg,
BounceKeysDlgProc,
(LPARAM)pGlobalData);
break;
case IDC_FILTER_TEST_EDIT:
switch (HIWORD(wParam))
{
case EN_SETFOCUS:
EnableFilterKeysTest(pGlobalData);
break;
case EN_KILLFOCUS:
DisableFilterKeysTest(pGlobalData);
break;
}
break;
case IDC_FILTER_SOUND_CHECK:
pGlobalData->filterKeys.dwFlags ^= FKF_CLICKON;
break;
case IDC_FILTER_REPEAT_BUTTON:
DialogBoxParam(hApplet,
MAKEINTRESOURCE(IDD_REPEATKEYSOPTIONS),
hwndDlg,
RepeatKeysDlgProc,
(LPARAM)pGlobalData);
break;
case IDC_FILTER_STATUS_CHECK:
pGlobalData->filterKeys.dwFlags ^= FKF_INDICATOR;
break;
case IDOK:
EndDialog(hwndDlg,
(pGlobalData->filterKeys.dwFlags != pGlobalData->oldFilterKeys.dwFlags));
break;
case IDCANCEL:
EndDialog(hwndDlg, FALSE);
break;
default:
break;
}
break;
}
return FALSE;
}
/* Property page dialog callback */
INT_PTR CALLBACK
ToggleKeysDlgProc(HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
PGLOBAL_DATA pGlobalData;
pGlobalData = (PGLOBAL_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
switch (uMsg)
{
case WM_INITDIALOG:
pGlobalData = (PGLOBAL_DATA)lParam;
SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pGlobalData);
memcpy(&pGlobalData->oldToggleKeys,
&pGlobalData->toggleKeys,
sizeof(TOGGLEKEYS));
CheckDlgButton(hwndDlg,
IDC_TOGGLE_ACTIVATE_CHECK,
pGlobalData->toggleKeys.dwFlags & TKF_HOTKEYACTIVE ? BST_CHECKED : BST_UNCHECKED);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_TOGGLE_ACTIVATE_CHECK:
pGlobalData->toggleKeys.dwFlags ^= TKF_HOTKEYACTIVE;
break;
case IDOK:
EndDialog(hwndDlg,
(pGlobalData->toggleKeys.dwFlags != pGlobalData->oldToggleKeys.dwFlags));
break;
case IDCANCEL:
EndDialog(hwndDlg, FALSE);
break;
default:
break;
}
break;
}
return FALSE;
}
/* Property page dialog callback */
INT_PTR CALLBACK
KeyboardPageProc(HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
PGLOBAL_DATA pGlobalData;
LPPSHNOTIFY lppsn;
pGlobalData = (PGLOBAL_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
switch (uMsg)
{
case WM_INITDIALOG:
pGlobalData = (PGLOBAL_DATA)((LPPROPSHEETPAGE)lParam)->lParam;
if (pGlobalData == NULL)
return FALSE;
SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pGlobalData);
CheckDlgButton(hwndDlg,
IDC_STICKY_BOX,
pGlobalData->stickyKeys.dwFlags & SKF_STICKYKEYSON ? BST_CHECKED : BST_UNCHECKED);
CheckDlgButton(hwndDlg,
IDC_FILTER_BOX,
pGlobalData->filterKeys.dwFlags & FKF_FILTERKEYSON ? BST_CHECKED : BST_UNCHECKED);
CheckDlgButton(hwndDlg,
IDC_TOGGLE_BOX,
pGlobalData->toggleKeys.dwFlags & TKF_TOGGLEKEYSON ? BST_CHECKED : BST_UNCHECKED);
CheckDlgButton(hwndDlg,
IDC_KEYBOARD_EXTRA,
pGlobalData->bKeyboardPref ? BST_CHECKED : BST_UNCHECKED);
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_STICKY_BOX:
pGlobalData->stickyKeys.dwFlags ^= SKF_STICKYKEYSON;
PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
break;
case IDC_STICKY_BUTTON:
if (DialogBoxParam(hApplet,
MAKEINTRESOURCE(IDD_STICKYKEYSOPTIONS),
hwndDlg,
StickyKeysDlgProc,
(LPARAM)pGlobalData))
PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
break;
case IDC_FILTER_BOX:
pGlobalData->filterKeys.dwFlags ^= FKF_FILTERKEYSON;
PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
break;
case IDC_FILTER_BUTTON:
if (DialogBoxParam(hApplet,
MAKEINTRESOURCE(IDD_FILTERKEYSOPTIONS),
hwndDlg,
FilterKeysDlgProc,
(LPARAM)pGlobalData))
PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
break;
case IDC_TOGGLE_BOX:
pGlobalData->toggleKeys.dwFlags ^= TKF_TOGGLEKEYSON;
PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
break;
case IDC_TOGGLE_BUTTON:
if (DialogBoxParam(hApplet,
MAKEINTRESOURCE(IDD_TOGGLEKEYSOPTIONS),
hwndDlg,
ToggleKeysDlgProc,
(LPARAM)pGlobalData))
PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
break;
case IDC_KEYBOARD_EXTRA:
pGlobalData->bKeyboardPref = !pGlobalData->bKeyboardPref;
PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
break;
default:
break;
}
break;
case WM_NOTIFY:
lppsn = (LPPSHNOTIFY)lParam;
if (lppsn->hdr.code == PSN_APPLY)
{
SystemParametersInfo(SPI_SETSTICKYKEYS,
sizeof(STICKYKEYS),
&pGlobalData->stickyKeys,
SPIF_UPDATEINIFILE | SPIF_SENDCHANGE /*0*/);
SystemParametersInfo(SPI_SETFILTERKEYS,
sizeof(FILTERKEYS),
&pGlobalData->filterKeys,
SPIF_UPDATEINIFILE | SPIF_SENDCHANGE /*0*/);
SystemParametersInfo(SPI_SETTOGGLEKEYS,
sizeof(TOGGLEKEYS),
&pGlobalData->toggleKeys,
SPIF_UPDATEINIFILE | SPIF_SENDCHANGE /*0*/);
SystemParametersInfo(SPI_SETKEYBOARDPREF,
pGlobalData->bKeyboardPref,
NULL,
SPIF_UPDATEINIFILE | SPIF_SENDCHANGE /*0*/);
return TRUE;
}
break;
}
return FALSE;
}