Fix a cut & paste bug.
[reactos.git] / reactos / dll / cpl / access / keyboard.c
index 5e6c505..a0b2efa 100644 (file)
 /* $Id$
  *
- * PROJECT:         ReactOS System Control Panel
+ * PROJECT:         ReactOS Accessibility Control Panel
  * LICENSE:         GPL - See COPYING in the top level directory
- * FILE:            lib/cpl/system/advanced.c
- * PURPOSE:         Memory, start-up and profiles settings
+ * FILE:            dll/cpl/access/keyboard.c
+ * PURPOSE:         Keyboard-related accessibility settings
  * COPYRIGHT:       Copyright 2004 Johannes Anderwald (j_anderw@sbox.tugraz.at)
- * UPDATE HISTORY:
- *      03-04-2004  Created
+ *                  Copyright 2007 Eric Kohl
  */
+
 #include <windows.h>
 #include <stdlib.h>
+#include <stdio.h>
+#include <commctrl.h>
+#include <prsht.h>
+#include <tchar.h>
 #include "resource.h"
 #include "access.h"
 
+
+#define BOUNCETICKS 5
+static INT nBounceArray[BOUNCETICKS] = {500, 700, 1000, 1500, 2000};
+
+#define DELAYTICKS 5
+static INT nDelayArray[DELAYTICKS] = {300, 700, 1000, 1500, 2000};
+
+#define REPEATTICKS 6
+static INT nRepeatArray[REPEATTICKS] = {300, 500, 700, 1000, 1500, 2000};
+
+#define WAITTICKS 10
+static INT 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
-KeyboardPageProc(
-  HWND hwndDlg,
-  UINT uMsg,
-  WPARAM wParam,
-  LPARAM lParam
-)
+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)
 {
-  UNREFERENCED_PARAMETER(lParam)
-  UNREFERENCED_PARAMETER(hwndDlg)
-  switch(uMsg)
-  {
-    case WM_INITDIALOG:
-      break;
-    case WM_COMMAND:
+    PGLOBAL_DATA pGlobalData;
+    INT i, n;
+
+    pGlobalData = (PGLOBAL_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
+
+    switch (uMsg)
     {
-      switch(LOWORD(wParam))
-      {
-        case IDC_STICKY_BOX:
-        {
-          break;
-        }
-
-        case IDC_STICKY_BUTTON:
-        {
-          break;
-        }
-
-        case IDC_FILTER_BOX:
-        {
-          break;
-        }
-
-        case IDC_FILTER_BUTTON:
-        {
-          break;
-        }
-
-        case IDC_TOGGLE_BOX:
-        {
-          break;
-        }
-
-        case IDC_TOGGLE_BUTTON:
-        {
-          break;
-        }
-        default:
-           break;
-      }
+        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;
+
+    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,
+                                   (DLGPROC)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,
+                                   (DLGPROC)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,
+                                       (DLGPROC)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,
+                                       (DLGPROC)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,
+                                       (DLGPROC)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;
 }