// ************************************************************************** // Access.c // // Accessability Property sheet page creator // // ************************************************************************** #include "Access.h" #ifdef UNICODE // Windows uses UNICODE #define _UNICODE // but tchar.h uses _UNICODE #endif DWORD g_dwOrigFKFlags; BOOL g_bFKOn; #include #include #include #define OLDDISABLED 32760 #ifndef FKF_VALID #define FKF_VALID 0x0000007F #endif #ifndef SKF_VALID #define SKF_VALID 0x000001FF #endif #ifndef MKF_VALID #define MKF_VALID 0x000000FF #endif #ifndef ATF_VALID #define ATF_VALID 0x00000003 #endif #ifndef SSF_VALID #define SSF_VALID 0x00000007 #endif #ifndef TKF_VALID #define TKF_VALID 0x0000003F #endif ////////////////////////////////////////////////////////////////////////// // collection of data that represents the saved accessability state typedef struct ACCSTATE // as { // Keyboard property page STICKYKEYS sk; FILTERKEYS fk; TOGGLEKEYS tk; BOOL fExtraKeyboardHelp; // Sound Property page SOUNDSENTRY ss; BOOL fShowSounds; // Display Property page HIGHCONTRAST hc; TCHAR szDefaultScheme[256]; // hc.lpszDefaultScheme CARET_SETTINGS cs; // Mouse Property page MOUSEKEYS mk; // General Property page BOOL fShowWarnMsgOnFeatureActivate; BOOL fPlaySndOnFeatureActivate; ACCESSTIMEOUT ato; SERIALKEYS serk; TCHAR szActivePort[MAX_PATH]; // serk.szActivePort TCHAR szPort[MAX_PATH]; // serk.szPort } ACCSTATE, *PACCSTATE; ////////////////////////////////////////////////////////////////////////// extern BOOL g_SPISetValue = FALSE; static ACCSTATE s_asOrg; // original settings from app start-up static ACCSTATE s_asPrev; // previous saved settings extern BOOL g_fWinNT = -1; // TRUE if we're running on NT and must // disable some features extern BOOL g_fSaveSettings = TRUE; extern BOOL g_fShowWarnMsgOnFeatureActivate = TRUE; extern BOOL g_fPlaySndOnFeatureActivate = TRUE; extern BOOL g_fCopyToLogon = FALSE; extern BOOL g_fCopyToDefault = FALSE; // Keyboard property page // extern STICKYKEYS g_sk = {0}; STICKYKEYS g_sk; FILTERKEYS g_fk; // g_dwLastBounceKeySetting, g_nLastRepeatDelay, g_nLastRepeatRate // and g_nLastWait are part of FilterKeys DWORD g_dwLastBounceKeySetting = 0; DWORD g_nLastRepeatDelay = 0; DWORD g_nLastRepeatRate = 0; DWORD g_nLastWait = 0; TOGGLEKEYS g_tk; BOOL g_fExtraKeyboardHelp = TRUE; // Sound Property page SOUNDSENTRY g_ss; BOOL g_fShowSounds; // Display Property page HIGHCONTRAST g_hc; CARET_SETTINGS g_cs; // Mouse Property page MOUSEKEYS g_mk; // General Property page ACCESSTIMEOUT g_ato; SERIALKEYS g_serk; TCHAR g_szActivePort[MAX_PATH]; TCHAR g_szPort[MAX_PATH]; #define CONTROL_PANEL_DESKTOP TEXT("Control Panel\\Desktop") #define CURSOR_BLINK_RATE TEXT("CursorBlinkRate") #define DEFAULT_BLINK_RATE 530 ////////////////////////////////////////////////////////////////////////// void CopyHighContrast(LPHIGHCONTRAST phcDest, LPHIGHCONTRAST phcSrc) { LPTSTR lpszDefaultScheme = phcDest->lpszDefaultScheme; memcpy(phcDest, phcSrc, sizeof(*phcDest)); phcDest->lpszDefaultScheme = lpszDefaultScheme; if (NULL != phcDest->lpszDefaultScheme) { lstrcpy(phcDest->lpszDefaultScheme, phcSrc->lpszDefaultScheme); } } ////////////////////////////////////////////////////////////////////////// BOOL IsHighContrastEqual(LPHIGHCONTRAST phcDest, LPHIGHCONTRAST phcSrc) { BOOL fIsEqual = FALSE; LPTSTR lpszDefaultScheme = phcDest->lpszDefaultScheme; // Temporarily make the pointers match phcDest->lpszDefaultScheme = phcSrc->lpszDefaultScheme; // match the bits of the structures and the pointed to data fIsEqual = (0 == memcmp(phcDest, phcSrc, sizeof(*phcDest)) && 0 == lstrcmp(lpszDefaultScheme, phcSrc->lpszDefaultScheme)); phcDest->lpszDefaultScheme = lpszDefaultScheme; return(fIsEqual); } ////////////////////////////////////////////////////////////////////////// void CopySerialKeys(LPSERIALKEYS pskDest, LPSERIALKEYS pskSrc) { LPTSTR lpszActivePort = pskDest->lpszActivePort; LPTSTR lpszPort = pskDest->lpszPort; memcpy(pskDest, pskSrc, sizeof(*pskDest)); pskDest->lpszActivePort = lpszActivePort; if (NULL != pskDest->lpszActivePort) { lstrcpy(pskDest->lpszActivePort, pskSrc->lpszActivePort); } pskDest->lpszPort = lpszPort; if (NULL != pskDest->lpszPort) { lstrcpy(pskDest->lpszPort, pskSrc->lpszPort); } } ////////////////////////////////////////////////////////////////////////// BOOL IsSerialKeysEqual(LPSERIALKEYS pskDest, LPSERIALKEYS pskSrc) { BOOL fIsEqual = FALSE; LPTSTR lpszActivePort = pskDest->lpszActivePort; LPTSTR lpszPort = pskDest->lpszPort; // Temporarily make the pointers match pskDest->lpszActivePort = pskSrc->lpszActivePort; pskDest->lpszPort = pskSrc->lpszPort; // match the bits of the structures and the pointed to data fIsEqual = (0 == memcmp(pskDest, pskSrc, sizeof(*pskDest)) && (NULL == lpszActivePort || 0 == lstrcmp(lpszActivePort, pskSrc->lpszActivePort)) && (NULL == lpszPort || 0 == lstrcmp(lpszPort, pskSrc->lpszPort))); pskDest->lpszActivePort = lpszActivePort; pskDest->lpszPort = lpszPort; return(fIsEqual); } ////////////////////////////////////////////////////////////////////////// BOOL IsAccStateEqual(PACCSTATE pasDest, PACCSTATE pasSrc) { BOOL fIsEqual = FALSE; HIGHCONTRAST hc = pasDest->hc; SERIALKEYS serk = pasDest->serk; int nLen; // Clear out the unused sections of the string buffers nLen = lstrlen(pasDest->szDefaultScheme); memset(&pasDest->szDefaultScheme[nLen], 0, sizeof(pasDest->szDefaultScheme)-nLen*sizeof(*pasDest->szDefaultScheme)); nLen = lstrlen(pasDest->szActivePort); memset(&pasDest->szActivePort[nLen], 0, sizeof(pasDest->szActivePort)-nLen*sizeof(*pasDest->szActivePort)); nLen = lstrlen(pasDest->szPort); memset(&pasDest->szPort[nLen], 0, sizeof(pasDest->szPort)-nLen*sizeof(*pasDest->szPort)); nLen = lstrlen(pasSrc->szDefaultScheme); memset(&pasSrc->szDefaultScheme[nLen], 0, sizeof(pasSrc->szDefaultScheme)-nLen*sizeof(*pasSrc->szDefaultScheme)); nLen = lstrlen(pasSrc->szActivePort); memset(&pasSrc->szActivePort[nLen], 0, sizeof(pasSrc->szActivePort)-nLen*sizeof(*pasSrc->szActivePort)); nLen = lstrlen(pasSrc->szActivePort); memset(&pasSrc->szPort[nLen], 0, sizeof(pasSrc->szPort)-nLen*sizeof(*pasSrc->szPort)); // Temporarily make the elements with pointers match pasDest->hc = pasSrc->hc; pasDest->serk = pasSrc->serk; // match the bits of the structures and the elements with pointers fIsEqual = (0 == memcmp(pasDest, pasSrc, sizeof(*pasDest)) && IsHighContrastEqual(&hc, &pasSrc->hc) && IsSerialKeysEqual(&serk, &pasSrc->serk)); pasDest->hc = hc; pasDest->serk = serk; return(fIsEqual); } ////////////////////////////////////////////////////////////////////////// int WINAPI RegQueryInt (int nDefault, HKEY hkey, LPTSTR lpSubKey, LPTSTR lpValueName) { DWORD dwType; DWORD dwVal = nDefault; DWORD cbData = sizeof(int); if (ERROR_SUCCESS == RegOpenKeyEx(hkey, lpSubKey, 0, KEY_QUERY_VALUE, &hkey)) { RegQueryValueEx(hkey, lpValueName, NULL, &dwType, (PBYTE) &dwVal, &cbData); RegCloseKey(hkey); } return(dwVal); } ////////////////////////////////////////////////////////////////////////// BOOL WINAPI RegSetInt (HKEY hkey, LPTSTR lpSubKey, LPTSTR lpValueName, int nVal) { BOOL fOk = FALSE; DWORD dwDisposition; LONG lRet; if (ERROR_SUCCESS == RegCreateKeyEx(hkey, lpSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hkey, &dwDisposition)) { lRet = RegSetValueEx(hkey, lpValueName, 0, REG_DWORD, (CONST BYTE *) &nVal, sizeof(nVal)); fOk = (ERROR_SUCCESS == lRet); RegCloseKey(hkey); } return fOk; } ////////////////////////////////////////////////////////////////////////// void WINAPI RegQueryStr( LPTSTR lpDefault, HKEY hkey, LPTSTR lpSubKey, LPTSTR lpValueName, LPTSTR lpszValue, DWORD cbData) // note this is bytes, not characters. { DWORD dwType; DWORD dwOrigCount = cbData; lstrcpy(lpszValue, lpDefault); if (ERROR_SUCCESS == RegOpenKeyEx(hkey, lpSubKey, 0, KEY_QUERY_VALUE, &hkey)) { RegQueryValueEx(hkey, lpValueName, NULL, &dwType, (PBYTE) lpszValue, &cbData); lpszValue[dwOrigCount/sizeof (TCHAR)-1] = TEXT('\0'); RegCloseKey(hkey); } } /***************************************************************************\ **AccessWriteProfileString * * History: * 12-19-95 a-jimhar Created (was called AccessWriteProfileString) * 02-08-95 a-jimhar revised and moved from accrare.c to access.c \***************************************************************************/ BOOL RegSetStr( HKEY hkey, LPCTSTR lpSection, LPCTSTR lpKeyName, LPCTSTR lpString) { BOOL fRet = FALSE; LONG lErr; DWORD dwDisposition; lErr = RegCreateKeyEx( hkey, lpSection, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hkey, &dwDisposition); if (ERROR_SUCCESS == lErr) { if (NULL != lpString) { lErr = RegSetValueEx( hkey, lpKeyName, 0, REG_SZ, (CONST BYTE *)lpString, (lstrlen(lpString) + 1) * sizeof(*lpString)); } else { lErr = RegSetValueEx( hkey, lpKeyName, 0, REG_SZ, (CONST BYTE *)__TEXT(""), 1 * sizeof(*lpString)); } if (ERROR_SUCCESS == lErr) { fRet = TRUE; } RegCloseKey(hkey); } return(fRet); } DWORD WINAPI RegQueryStrDW( DWORD dwDefault, HKEY hkey, LPTSTR lpSubKey, LPTSTR lpValueName) { DWORD dwRet = dwDefault; TCHAR szTemp[40]; TCHAR szDefault[40]; const LPTSTR pwszd = __TEXT("%d"); wsprintf(szDefault, pwszd, dwDefault); RegQueryStr( szDefault, hkey, lpSubKey, lpValueName, szTemp, sizeof(szTemp)); dwRet = _ttol(szTemp); return dwRet; } BOOL RegSetStrDW( HKEY hkey, LPTSTR lpSection, LPCTSTR lpKeyName, DWORD dwValue) { BOOL fRet; TCHAR szTemp[40]; const LPTSTR pwszd = __TEXT("%d"); wsprintf(szTemp, pwszd, dwValue); fRet = RegSetStr(hkey, lpSection, lpKeyName, szTemp); return fRet; } ////////////////////////////////////////////////////////////////////////// /*------------------------------------------------------------------ * Function void KillAccStat() * * Purpose Check if accstat is already running. If it is we need * to check to see if it should be. It should only be running * if each feature that is on also has the 'show status on * screen flag checked. If not we want to kill accstat. * * Params: None * * Return: TRUE if we had to kill accstat * FALSE if accstat not running/valid session *------------------------------------------------------------------*/ void KillAccStat (void) { BOOL fCanTurnOff = FALSE; // Can we turn off accstat due to invalid feature? BOOL fValidFeature = FALSE; // Are there any valid features? // Accstat may be running. Determine if it should be running // We need to check the FilterKeys, MouseKeys and StickyKeys if (g_sk.dwFlags & SKF_STICKYKEYSON) if (!(g_sk.dwFlags & SKF_INDICATOR)) fCanTurnOff = TRUE; // A mismatched flag - we MAY be able to turn off. else fValidFeature = TRUE; // A valid feature - we CAN't turn off accstat. if (g_fk.dwFlags & FKF_FILTERKEYSON) if (!(g_fk.dwFlags & FKF_INDICATOR)) fCanTurnOff = TRUE; // A mismatched flag - we MAY be able to turn off. else fValidFeature = TRUE; // A valid feature - we CAN't turn off accstat. if (g_mk.dwFlags & MKF_MOUSEKEYSON) if (!(g_mk.dwFlags & MKF_INDICATOR)) fCanTurnOff = TRUE; // A mismatched flag - we MAY be able to turn off. else fValidFeature = TRUE; // A valid feature - we CAN't turn off accstat. // Now we have two flags: fCanTurnOff is TRUE if there is a mismatched flag set // ie, feature on, indicator off. ValidFeature is TRUE if any feature has // ON and INDICATOR set which implies accstat must remain active. if (!fValidFeature && fCanTurnOff) { TCHAR szBuf[256]; HWND hwndAccStat; LoadString(g_hinst, IDS_ACCSTAT_WINDOW_TITLE, szBuf, ARRAY_SIZE(szBuf)); if (IsWindow(hwndAccStat = FindWindow(NULL, szBuf))) { // Note sending 1 as the lParam tells accstat to shutup and // go away NOW. SendMessage(hwndAccStat, WM_SYSCOMMAND, SC_CLOSE, 1); } } } ////////////////////////////////////////////////////////////////////////// void WINAPI GetAccessibilitySettings (void) { BOOL fUpdate; if (g_fWinNT == -1) { OSVERSIONINFO osvi; osvi.dwOSVersionInfoSize = sizeof(osvi); GetVersionEx(&osvi); g_fWinNT = (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT); } g_fShowWarnMsgOnFeatureActivate = (BOOL) RegQueryInt(TRUE, HKEY_CURRENT_USER, GENERAL_KEY, WARNING_SOUNDS); s_asPrev.fShowWarnMsgOnFeatureActivate = g_fShowWarnMsgOnFeatureActivate; // Query the Sound On Activation entry g_fPlaySndOnFeatureActivate = (BOOL) RegQueryInt(TRUE, HKEY_CURRENT_USER, GENERAL_KEY, SOUND_ON_ACTIVATION); s_asPrev.fPlaySndOnFeatureActivate = g_fPlaySndOnFeatureActivate; g_fSaveSettings = TRUE; // Keyboard property page g_sk.cbSize = sizeof(g_sk); AccessSystemParametersInfo(SPI_GETSTICKYKEYS, sizeof(g_sk), &g_sk, 0); s_asPrev.sk = g_sk; g_fk.cbSize = sizeof(g_fk); AccessSystemParametersInfo(SPI_GETFILTERKEYS, sizeof(g_fk), &g_fk, 0); g_fk.dwFlags |= FKF_AVAILABLE; // FILTERKEYS used to use OLDDISABLED as it's "unused" flag. This doesn't // work very well on NT (SPI_SETFILTERKEYS calls fail). We now use 0 // for disabled values. Take this opertunity to change any OLDDISABLED // values to 0 and save if needed. fUpdate = FALSE; if (OLDDISABLED == g_fk.iBounceMSec) { g_fk.iBounceMSec = 0; fUpdate = TRUE; } if (OLDDISABLED == g_fk.iDelayMSec) { g_fk.iDelayMSec = 0; fUpdate = TRUE; } if (OLDDISABLED == g_fk.iRepeatMSec) { g_fk.iRepeatMSec = 0; fUpdate = TRUE; } if (OLDDISABLED == g_fk.iWaitMSec) { g_fk.iWaitMSec = 0; fUpdate = TRUE; } if (fUpdate) { AccessSystemParametersInfo( SPI_SETFILTERKEYS, sizeof(g_fk), &g_fk, SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE); } s_asPrev.fk = g_fk; // fix Filter keys bug g_dwOrigFKFlags = g_fk.dwFlags; g_bFKOn = g_fk.dwFlags & FKF_FILTERKEYSON; // g_dwLastBounceKeySetting, g_nLastRepeatDelay, g_nLastRepeatRate // and g_nLastWait are part of FilterKeys if (0 != g_fk.iBounceMSec) { // Bounce keys enabeled g_fk.iDelayMSec = 0; g_fk.iRepeatMSec = 0; g_fk.iWaitMSec = 0; g_dwLastBounceKeySetting = g_fk.iBounceMSec; g_nLastRepeatDelay = RegQueryInt(0, HKEY_CURRENT_USER, FILTER_KEY, LAST_REPEAT_DELAY); g_nLastRepeatRate = RegQueryInt(0, HKEY_CURRENT_USER, FILTER_KEY, LAST_REPEAT_RATE); g_nLastWait = RegQueryInt(0, HKEY_CURRENT_USER, FILTER_KEY, LAST_WAIT); } else { if (0 == g_fk.iDelayMSec) { g_fk.iRepeatMSec = 0; } g_dwLastBounceKeySetting = RegQueryInt(0, HKEY_CURRENT_USER, FILTER_KEY, LAST_BOUNCE_SETTING); g_nLastRepeatDelay = RegQueryInt(0, HKEY_CURRENT_USER, FILTER_KEY, LAST_REPEAT_DELAY); g_nLastRepeatRate = RegQueryInt(0, HKEY_CURRENT_USER, FILTER_KEY, LAST_REPEAT_RATE); if (0 != g_fk.iWaitMSec) { g_nLastWait = g_fk.iWaitMSec; } else { g_nLastWait = RegQueryInt(0, HKEY_CURRENT_USER, FILTER_KEY, LAST_WAIT); } } g_tk.cbSize = sizeof(g_tk); AccessSystemParametersInfo(SPI_GETTOGGLEKEYS, sizeof(g_tk), &g_tk, 0); s_asPrev.tk = g_tk; AccessSystemParametersInfo(SPI_GETKEYBOARDPREF, 0, &g_fExtraKeyboardHelp, 0); s_asPrev.fExtraKeyboardHelp = g_fExtraKeyboardHelp; // Sound Property page g_ss.cbSize = sizeof(g_ss); AccessSystemParametersInfo(SPI_GETSOUNDSENTRY, sizeof(g_ss), &g_ss, 0); s_asPrev.ss = g_ss; SystemParametersInfo(SPI_GETSHOWSOUNDS, 0, &g_fShowSounds, 0); // BUG, BUG GetSystemMetrics() is not updating value on reboot :a-anilk // g_fShowSounds = GetSystemMetrics(SM_SHOWSOUNDS); s_asPrev.fShowSounds = g_fShowSounds; // Display Property page g_hc.cbSize = sizeof(g_hc); AccessSystemParametersInfo(SPI_GETHIGHCONTRAST, sizeof(g_hc), &g_hc, 0); // Currently NT will not store these flags. We fake them so we // can tell if they actually changed. s_asPrev.hc.lpszDefaultScheme = s_asPrev.szDefaultScheme; CopyHighContrast(&s_asPrev.hc, &g_hc); SystemParametersInfo(SPI_GETCARETWIDTH, 0, (PVOID)&g_cs.dwCaretWidth, 0); g_cs.dwCaretBlinkRate = RegQueryStrDW( DEFAULT_BLINK_RATE , HKEY_CURRENT_USER , CONTROL_PANEL_DESKTOP , CURSOR_BLINK_RATE); if (g_cs.dwCaretBlinkRate == BLINK_OFF) g_cs.dwCaretBlinkRate = CURSORMAX; s_asPrev.cs.dwCaretBlinkRate = g_cs.dwCaretBlinkRate; s_asPrev.cs.dwCaretWidth = g_cs.dwCaretWidth; // Mouse Property page g_mk.cbSize = sizeof(g_mk); AccessSystemParametersInfo(SPI_GETMOUSEKEYS, sizeof(g_mk), &g_mk, 0); s_asPrev.mk = g_mk; // General Property page g_ato.cbSize = sizeof(g_ato); AccessSystemParametersInfo(SPI_GETACCESSTIMEOUT, sizeof(g_ato), &g_ato, 0); s_asPrev.ato = g_ato; g_serk.cbSize = sizeof(g_serk); g_serk.lpszActivePort = g_szActivePort; g_serk.lpszPort = g_szPort; AccessSystemParametersInfo(SPI_GETSERIALKEYS, sizeof(g_serk), &g_serk, 0); s_asPrev.serk.lpszActivePort = s_asPrev.szActivePort; s_asPrev.serk.lpszPort = s_asPrev.szPort; CopySerialKeys(&s_asPrev.serk, &g_serk); if (NULL == s_asOrg.hc.lpszDefaultScheme) { // s_asOrg has not yet been initialized s_asOrg = s_asPrev; s_asOrg.hc.lpszDefaultScheme = s_asOrg.szDefaultScheme; s_asOrg.serk.lpszActivePort = s_asOrg.szActivePort; s_asOrg.serk.lpszPort = s_asOrg.szPort; } } ////////////////////////////////////////////////////////////////////////// //a-anilk: Change, Admin options, Keyboard flags: 05/06/99 void WINAPI SetAccessibilitySettings (void) { HKEY hkey; DWORD dwDisposition; UINT fWinIni = SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE; BOOL fAnyNotifyChange = FALSE; g_SPISetValue = TRUE; SetCursor(LoadCursor(NULL, IDC_WAIT)); if (g_fShowWarnMsgOnFeatureActivate) { g_hc.dwFlags |= HCF_CONFIRMHOTKEY; g_fk.dwFlags |= FKF_CONFIRMHOTKEY; g_sk.dwFlags |= SKF_CONFIRMHOTKEY; g_mk.dwFlags |= MKF_CONFIRMHOTKEY; g_tk.dwFlags |= TKF_CONFIRMHOTKEY; } else { g_hc.dwFlags &= ~HCF_CONFIRMHOTKEY; g_fk.dwFlags &= ~FKF_CONFIRMHOTKEY; g_sk.dwFlags &= ~SKF_CONFIRMHOTKEY; g_mk.dwFlags &= ~MKF_CONFIRMHOTKEY; g_tk.dwFlags &= ~TKF_CONFIRMHOTKEY; } if (g_fPlaySndOnFeatureActivate) { g_hc.dwFlags |= HCF_HOTKEYSOUND; g_fk.dwFlags |= FKF_HOTKEYSOUND; g_sk.dwFlags |= SKF_HOTKEYSOUND; g_mk.dwFlags |= MKF_HOTKEYSOUND; g_tk.dwFlags |= TKF_HOTKEYSOUND; g_ato.dwFlags |= ATF_ONOFFFEEDBACK; } else { g_hc.dwFlags &= ~HCF_HOTKEYSOUND; g_fk.dwFlags &= ~FKF_HOTKEYSOUND; g_sk.dwFlags &= ~SKF_HOTKEYSOUND; g_mk.dwFlags &= ~MKF_HOTKEYSOUND; g_tk.dwFlags &= ~TKF_HOTKEYSOUND; g_ato.dwFlags &= ~ATF_ONOFFFEEDBACK; } // Keyboard property page if (0 != memcmp(&g_sk, &s_asPrev.sk, sizeof(g_sk))) { if (g_fWinNT) { g_sk.dwFlags &= SKF_VALID; } AccessSystemParametersInfo(SPI_SETSTICKYKEYS, sizeof(g_sk), &g_sk, fWinIni); s_asPrev.sk = g_sk; fAnyNotifyChange = TRUE; } if (g_bFKOn) g_fk.dwFlags |= FKF_FILTERKEYSON; else g_fk.dwFlags &= ~FKF_FILTERKEYSON; g_dwOrigFKFlags = g_fk.dwFlags; if (0 != memcmp(&g_fk, &s_asPrev.fk, sizeof(g_fk))) { if (g_fWinNT) { g_fk.dwFlags &= FKF_VALID; } // g_dwLastBounceKeySetting, g_nLastRepeatDelay, g_nLastRepeatRate // and g_nLastWait are part of FilterKeys if (0 != g_fk.iBounceMSec) { // Bounce keys enabeled g_fk.iDelayMSec = 0; g_fk.iRepeatMSec = 0; g_fk.iWaitMSec = 0; g_dwLastBounceKeySetting = g_fk.iBounceMSec; } else { g_nLastWait = g_fk.iWaitMSec; if (0 != g_fk.iDelayMSec) { // Slow key enabled g_nLastRepeatDelay = g_fk.iDelayMSec; g_nLastRepeatRate = g_fk.iRepeatMSec; } else { // neither Bounce or Slow g_fk.iRepeatMSec = 0; } } AccessSystemParametersInfo(SPI_SETFILTERKEYS, sizeof(g_fk), &g_fk, fWinIni); s_asPrev.fk = g_fk; fAnyNotifyChange = TRUE; } // always save these RegSetInt(HKEY_CURRENT_USER, FILTER_KEY, LAST_BOUNCE_SETTING, g_dwLastBounceKeySetting); RegSetInt(HKEY_CURRENT_USER, FILTER_KEY, LAST_REPEAT_DELAY, g_nLastRepeatDelay); RegSetInt(HKEY_CURRENT_USER, FILTER_KEY, LAST_REPEAT_RATE, g_nLastRepeatRate); RegSetInt(HKEY_CURRENT_USER, FILTER_KEY, LAST_WAIT, g_nLastWait); if (0 != memcmp(&g_tk, &s_asPrev.tk, sizeof(g_tk))) { if (g_fWinNT) { g_tk.dwFlags &= TKF_VALID; } AccessSystemParametersInfo(SPI_SETTOGGLEKEYS, sizeof(g_tk), &g_tk, fWinIni); s_asPrev.tk = g_tk; fAnyNotifyChange = TRUE; } if (g_fExtraKeyboardHelp != s_asPrev.fExtraKeyboardHelp) { // Set this too. Some controls check this flag...0x100B AccessSystemParametersInfo(SPI_SETKEYBOARDCUES, 0, IntToPtr(g_fExtraKeyboardHelp), fWinIni); AccessSystemParametersInfo(SPI_SETKEYBOARDPREF, g_fExtraKeyboardHelp, 0, fWinIni); s_asPrev.fExtraKeyboardHelp = g_fExtraKeyboardHelp; fAnyNotifyChange = TRUE; } // Display Property page if (!IsHighContrastEqual(&g_hc, &s_asPrev.hc)) { AccessSystemParametersInfo(SPI_SETHIGHCONTRAST, sizeof(g_hc), &g_hc, fWinIni); if (ERROR_SUCCESS == RegCreateKeyEx( HKEY_CURRENT_USER, HC_KEY, 0, __TEXT(""), REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hkey, &dwDisposition)) { RegSetValueEx(hkey, HIGHCONTRAST_SCHEME, 0, REG_SZ, (PBYTE) g_hc.lpszDefaultScheme, (lstrlen(g_hc.lpszDefaultScheme) + 1) * sizeof(*g_hc.lpszDefaultScheme)); RegSetValueEx(hkey, VOLATILE_SCHEME, 0, REG_SZ, (PBYTE) g_hc.lpszDefaultScheme, (lstrlen(g_hc.lpszDefaultScheme) + 1) * sizeof(*g_hc.lpszDefaultScheme)); RegCloseKey(hkey); hkey = NULL; } CopyHighContrast(&s_asPrev.hc, &g_hc); fAnyNotifyChange = TRUE; } if (g_cs.dwCaretBlinkRate != s_asPrev.cs.dwCaretBlinkRate) { DWORD dwCaretBlinkRate = (g_cs.dwCaretBlinkRate < CURSORMAX)?g_cs.dwCaretBlinkRate:BLINK_OFF; // Set the blink rate for this session SetCaretBlinkTime(dwCaretBlinkRate); // and persist it to the registry RegSetStrDW(HKEY_CURRENT_USER, CONTROL_PANEL_DESKTOP, CURSOR_BLINK_RATE, dwCaretBlinkRate); } if (g_cs.dwCaretWidth != s_asPrev.cs.dwCaretWidth) AccessSystemParametersInfo(SPI_SETCARETWIDTH, 0, IntToPtr(g_cs.dwCaretWidth), fWinIni); s_asPrev.cs = g_cs; // Mouse Property page if (0 != memcmp(&g_mk, &s_asPrev.mk, sizeof(g_mk))) { if (g_fWinNT) { g_mk.dwFlags &= MKF_VALID; } AccessSystemParametersInfo(SPI_SETMOUSEKEYS, sizeof(g_mk), &g_mk, fWinIni); s_asPrev.mk = g_mk; fAnyNotifyChange = TRUE; } // General Property page if (g_fPlaySndOnFeatureActivate) { g_ato.dwFlags |= ATF_ONOFFFEEDBACK; } else { g_ato.dwFlags &= ~ATF_ONOFFFEEDBACK; } if (0 != memcmp(&g_ato, &s_asPrev.ato, sizeof(g_ato))) { if (g_fWinNT) { g_ato.dwFlags &= ATF_VALID; } AccessSystemParametersInfo(SPI_SETACCESSTIMEOUT, sizeof(g_ato), &g_ato, fWinIni); s_asPrev.ato = g_ato; fAnyNotifyChange = TRUE; } if (!IsSerialKeysEqual(&g_serk, &s_asPrev.serk)) { AccessSystemParametersInfo(SPI_SETSERIALKEYS, sizeof(g_serk), &g_serk, fWinIni); CopySerialKeys(&s_asPrev.serk, &g_serk); fAnyNotifyChange = TRUE; } if (g_fSaveSettings) { if (RegCreateKeyEx(HKEY_CURRENT_USER, GENERAL_KEY, 0, __TEXT(""), REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hkey, &dwDisposition) == ERROR_SUCCESS) { // Save the Warning Sounds entry if (g_fShowWarnMsgOnFeatureActivate != s_asPrev.fShowWarnMsgOnFeatureActivate) { RegSetValueEx(hkey, WARNING_SOUNDS, 0, REG_DWORD, (PBYTE) &g_fShowWarnMsgOnFeatureActivate, sizeof(g_fShowWarnMsgOnFeatureActivate)); s_asPrev.fShowWarnMsgOnFeatureActivate = g_fShowWarnMsgOnFeatureActivate; } // Save the Sound On Activation entry if (g_fPlaySndOnFeatureActivate != s_asPrev.fPlaySndOnFeatureActivate) { RegSetValueEx(hkey, SOUND_ON_ACTIVATION, 0, REG_DWORD, (PBYTE) &g_fPlaySndOnFeatureActivate, sizeof(g_fPlaySndOnFeatureActivate)); s_asPrev.fPlaySndOnFeatureActivate = g_fPlaySndOnFeatureActivate; } RegCloseKey(hkey); hkey = NULL; } } // Sound Property page if (0 != memcmp(&g_ss, &s_asPrev.ss, sizeof(g_ss))) { if (g_fWinNT) { g_ss.dwFlags &= SSF_VALID; } AccessSystemParametersInfo(SPI_SETSOUNDSENTRY, sizeof(g_ss), &g_ss, fWinIni); s_asPrev.ss = g_ss; fAnyNotifyChange = TRUE; } // We do the sound property page last because the SPI_SETSHOWSOUNDS call is used // to send out notifications. We make this call if either g_fShowSounds changed // or we need to send out notifications // Changed Nov.18 '98 to send out WM_SETTINGSCHANGE Seperately. if (g_fShowSounds != s_asPrev.fShowSounds /*|| (fAnyNotifyChange && g_fSaveSettings)*/) { // if (g_fSaveSettings) fWinIni |= SPIF_SENDWININICHANGE; AccessSystemParametersInfo(SPI_SETSHOWSOUNDS, g_fShowSounds, NULL, fWinIni); s_asPrev.fShowSounds = g_fShowSounds; } g_SPISetValue = FALSE; // Do Admin options SaveDefaultSettings(g_fCopyToLogon, g_fCopyToDefault); SetCursor(LoadCursor(NULL, IDC_ARROW)); } ////////////////////////////////////////////////////////////////////////// INT_PTR WINAPI KeyboardDlg (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); INT_PTR WINAPI SoundDlg (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); INT_PTR WINAPI GeneralDlg (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); INT_PTR WINAPI DisplayDlg (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); INT_PTR WINAPI MouseDlg (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); #define MAX_PAGES 10 // ************************************************************************ // OpenAccessPropertySheet // Opens property sheet // ************************************************************************ BOOL OpenAccessPropertySheet (HWND hwnd, int nID) { HPROPSHEETPAGE rPages[MAX_PAGES]; PROPSHEETPAGE psp; PROPSHEETHEADER psh; INT_PTR nPsRet; KillAccStat(); GetAccessibilitySettings(); // Simple errorchecking - only allow control to move to tabs 0-4. // Any tab request greater than 4 is invalid - so default to tab 0 if ((nID < 0) || (nID > 4)) nID = 0; // Initialize the property sheets psh.dwSize = sizeof(psh); // SteveDon 5-26-98 // no longer use PSH_PROPTITLE because we want it to read "Accessibility Options" // rather than "Accessibility Properties" or "Properties for Accessibility" psh.dwFlags = 0; // psh.dwFlags = PSH_PROPTITLE; // | PSH_PROPSHEETPAGE | PSP_USEICONID; psh.hwndParent = hwnd; psh.hInstance = g_hinst; psh.pszCaption = MAKEINTRESOURCE(IDS_PROPERTY_TITLE); //ACCESSIBILITY); psh.pszIcon = MAKEINTRESOURCE(IDI_ACCESS); psh.nPages = 0; psh.nStartPage = 0; psh.phpage = rPages; // Add First Sheet, keyboard psp.dwSize = sizeof(psp); psp.dwFlags = PSP_DEFAULT; psp.hInstance = g_hinst; psp.pszTemplate = MAKEINTRESOURCE(IDD_KEYBOARD); psp.pfnDlgProc = KeyboardDlg; psp.lParam = 0; psh.phpage[psh.nPages] = CreatePropertySheetPage(&psp); if (psh.phpage[psh.nPages]) psh.nPages++; // Add second sheet, Sound psp.dwSize = sizeof(psp); psp.dwFlags = PSP_DEFAULT; psp.hInstance = g_hinst; psp.pszTemplate = MAKEINTRESOURCE(IDD_SOUND); psp.pfnDlgProc = SoundDlg; psp.lParam = 0; psh.phpage[psh.nPages] = CreatePropertySheetPage(&psp); if (psh.phpage[psh.nPages]) psh.nPages++; // Add third sheet, Display psp.dwSize = sizeof(psp); psp.dwFlags = PSP_DEFAULT; psp.hInstance = g_hinst; psp.pszTemplate = MAKEINTRESOURCE(IDD_DISPLAY); psp.pfnDlgProc = DisplayDlg; psp.lParam = 0; psh.phpage[psh.nPages] = CreatePropertySheetPage(&psp); if (psh.phpage[psh.nPages]) psh.nPages++; // Add fourth sheet, Mouse psp.dwSize = sizeof(psp); psp.dwFlags = PSP_DEFAULT; psp.hInstance = g_hinst; psp.pszTemplate = MAKEINTRESOURCE(IDD_MOUSE); psp.pfnDlgProc = MouseDlg; psp.lParam = 0; psh.phpage[psh.nPages] = CreatePropertySheetPage(&psp); if (psh.phpage[psh.nPages]) psh.nPages++; // Add fifth sheet, General psp.dwSize = sizeof(psp); psp.dwFlags = PSP_DEFAULT; psp.hInstance = g_hinst; psp.pszTemplate = MAKEINTRESOURCE(IDD_GENERAL); psp.pfnDlgProc = GeneralDlg; psp.lParam = 0; psh.phpage[psh.nPages] = CreatePropertySheetPage(&psp); if (psh.phpage[psh.nPages]) psh.nPages++; // Simple errorchecking - only allow control to move to tabs 0 to psh.nPages // Any tab request greater than psh.nPages is invalid if (0 <= nID && nID < (int)psh.nPages) { psh.nStartPage = nID; } nPsRet = PropertySheet(&psh); if ( nPsRet <= 0 ) return FALSE; else return TRUE; } ///////////////////////////////// End of File /////////////////////////////////