//--------------------------------------------------------------------------- // // File: plustab.cpp // // Main Implementation of the Effects page // //--------------------------------------------------------------------------- #include "precomp.hxx" #include "shlwapip.h" #include "shlguidp.h" #include "EffectsAdvPg.h" #include "store.h" #pragma hdrstop // OLE-Registry magic number GUID g_CLSID_CplExt = { 0x41e300e0, 0x78b6, 0x11ce, { 0x84, 0x9b, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00} }; #define SPI_GETKEYBOARDINDICATORS SPI_GETMENUUNDERLINES//0x100A #define SPI_SETKEYBOARDINDICATORS SPI_SETMENUUNDERLINES//0x100B #define SPI_GETFONTCLEARTYPE 116 #define SPI_SETFONTCLEARTYPE 117 //Defines for getting registry settings const TCHAR c_szHICKey[] = TEXT("Control Panel\\Desktop\\WindowMetrics"); // show icons using highest possible colors const TCHAR c_szHICVal[] = TEXT("Shell Icon BPP"); // (4 if the checkbox is false, otherwise 16, don't set it to anything else) const TCHAR c_szSSKey[] = TEXT("Control Panel\\Desktop"); const TCHAR c_szSSVal[] = TEXT("SmoothScroll"); const TCHAR c_szWMSISVal[] = TEXT("Shell Icon Size"); // Normal Icon Size (default 32 x 32) #ifdef INET_EXP_ICON const TCHAR c_szIEXP[] = TEXT("\\Program Files\\Microsoft Internet Explorer 4"); #endif // Handle to the DLL extern HINSTANCE g_hInst; BOOL g_bMirroredOS = FALSE; // vars needed for new shell api #define SZ_SHELL32 TEXT("shell32.dll") #define SZ_SHUPDATERECYCLEBINICON "SHUpdateRecycleBinIcon" // Parameter for GetProcAddr()... DO NOT TEXT("") IT! HINSTANCE g_hmodShell32 = NULL; typedef void (* PFNSHUPDATERECYCLEBINICON)( void ); // Function prototype BOOL CALLBACK PlusPackDlgProc( HWND hDlg, UINT uMessage, WPARAM wParam, LPARAM lParam ); // Icon Stuff int GetIconState (void); BOOL ChangeIconSizes(int iOldState, int iNewState); // animation stuff WPARAM GetAnimations(DWORD *pdwEffect); void SetAnimations(WPARAM wVal, DWORD dwEffect); BOOL DisplayFontSmoothingDetails(DWORD *pdwSetting) { return FALSE; } int GetBitsPerPixel(void) { int iBitsPerPixel = 8; HDC hDC = GetDC(NULL); if (hDC) { iBitsPerPixel = GetDeviceCaps(hDC, BITSPIXEL); ReleaseDC(NULL, hDC); } return iBitsPerPixel; } int GetIconState(void) { BOOL bRet; int iSize; bRet = GetRegValueInt(HKEY_CURRENT_USER, c_szHICKey, c_szWMSISVal, &iSize); if (bRet == FALSE) return ICON_DEFAULT; if (iSize == ICON_DEFAULT_NORMAL) return ICON_DEFAULT; else if (iSize == ICON_DEFAULT_LARGE) return ICON_LARGE; return ICON_INDETERMINATE; } BOOL ChangeIconSizes(int iOldState, int iNewState) { BOOL bRet; int iOldSize, iNewSize; int iHorz; int iVert; // Don't bother if nothing changed if (iOldState == iNewState) return FALSE; // Get New Size switch (iNewState) { case ICON_DEFAULT: iNewSize = ICON_DEFAULT_NORMAL; break; case ICON_LARGE: iNewSize = ICON_DEFAULT_LARGE; break; case ICON_INDETERMINATE: // Don't bother to change anything return FALSE; default: return FALSE; } // Get Original Size bRet = GetRegValueInt (HKEY_CURRENT_USER, c_szHICKey, c_szWMSISVal, &iOldSize); if (!bRet) { // Try geting system default instead iOldSize = GetSystemMetrics (SM_CXICON); } // Don't need to change size if nothing has really changed if (iNewSize == iOldSize) return FALSE; // Get new horizontal spacing iHorz = GetSystemMetrics (SM_CXICONSPACING); iHorz -= iOldSize; if (iHorz < 0) { iHorz = 0; } iHorz += iNewSize; // Get new vertical spacing iVert = GetSystemMetrics (SM_CYICONSPACING); iVert -= iOldSize; if (iVert < 0) { iVert = 0; } iVert += iNewSize; // Set New sizes and spacing bRet = SetRegValueInt( HKEY_CURRENT_USER, c_szHICKey, c_szWMSISVal, iNewSize ); if (!bRet) return FALSE; SystemParametersInfo( SPI_ICONHORIZONTALSPACING, iHorz, NULL, SPIF_UPDATEINIFILE ); SystemParametersInfo( SPI_ICONVERTICALSPACING, iVert, NULL, SPIF_UPDATEINIFILE ); // We did change the sizes return TRUE; } // // GetAnimations // // Get current state of animations (windows / menus / etc.). // WPARAM GetAnimations(DWORD *pdwEffect) { BOOL fMenu = FALSE, fWindow = FALSE, fCombo = FALSE, fSmooth = FALSE, fList = FALSE, fFade = FALSE; ANIMATIONINFO ai; ai.cbSize = sizeof(ai); if (SystemParametersInfo( SPI_GETANIMATION, sizeof(ai), (PVOID)&ai, 0 )) { fWindow = (ai.iMinAnimate) ? TRUE : FALSE; } SystemParametersInfo( SPI_GETCOMBOBOXANIMATION, 0, (PVOID)&fCombo, 0 ); SystemParametersInfo( SPI_GETLISTBOXSMOOTHSCROLLING, 0, (PVOID)&fList, 0 ); SystemParametersInfo( SPI_GETMENUANIMATION, 0, (PVOID)&fMenu, 0 ); fSmooth = (BOOL)GetRegValueDword( HKEY_CURRENT_USER, (LPTSTR)c_szSSKey, (LPTSTR)c_szSSVal ); if (fSmooth == REG_BAD_DWORD) { fSmooth = 1; } SystemParametersInfo( SPI_GETMENUFADE, 0, (PVOID)&fFade, 0 ); *pdwEffect = (fFade ? MENU_EFFECT_FADE : MENU_EFFECT_SCROLL); if (fMenu && fWindow && fCombo && fSmooth && fList) return BST_CHECKED; if ((!fMenu) && (!fWindow) && (!fCombo) && (!fSmooth) && (!fList)) return BST_UNCHECKED; return BST_INDETERMINATE; } // // SetAnimations // // Set animations according (windows / menus / etc.) according to flag. // void SetAnimations(WPARAM wVal, DWORD dwEffect) { ANIMATIONINFO ai; // Note, if the checkbox is indeterminate, we treat it like it was checked. // We should never get this far if the user didn't change something so this should be okay. BOOL bVal = (wVal == BST_UNCHECKED) ? 0 : 1; BOOL bEfx = (dwEffect == MENU_EFFECT_FADE) ? 1 : 0; ai.cbSize = sizeof(ai); ai.iMinAnimate = bVal; SystemParametersInfo( SPI_SETANIMATION, sizeof(ai), (PVOID)&ai, SPIF_UPDATEINIFILE ); SystemParametersInfo( SPI_SETCOMBOBOXANIMATION, 0, IntToPtr(bVal), SPIF_UPDATEINIFILE ); SystemParametersInfo( SPI_SETLISTBOXSMOOTHSCROLLING, 0, IntToPtr(bVal), SPIF_UPDATEINIFILE ); SystemParametersInfo( SPI_SETMENUANIMATION, 0, IntToPtr(bVal), SPIF_UPDATEINIFILE ); SystemParametersInfo( SPI_SETTOOLTIPANIMATION, 0, IntToPtr(bVal), SPIF_UPDATEINIFILE ); SetRegValueDword(HKEY_CURRENT_USER, (LPTSTR)c_szSSKey, (LPTSTR)c_szSSVal, bVal); SystemParametersInfo( SPI_SETMENUFADE, 0, IntToPtr(bEfx), SPIF_UPDATEINIFILE); SystemParametersInfo( SPI_SETTOOLTIPFADE, 0, IntToPtr(bEfx), SPIF_UPDATEINIFILE); SystemParametersInfo( SPI_SETSELECTIONFADE, 0, bVal ? IntToPtr(bEfx) : 0, SPIF_UPDATEINIFILE); } CEffectState::CEffectState() { } CEffectState::~CEffectState() { } HRESULT CEffectState::Load(void) { HRESULT hr = S_OK; // Get the values for the settings from the registry and set the checkboxes // Large Icons _nLargeIcon = GetIconState(); // Full Color Icons if(FALSE == GetRegValueInt(HKEY_CURRENT_USER, c_szHICKey, c_szHICVal, &_nHighIconColor)) // Key not in registry yet { _nHighIconColor = 4; } // Use animations _wpMenuAnimation = GetAnimations(&_dwAnimationEffect); // Smooth edges of screen fonts _fFontSmoothing = FALSE; SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, (PVOID)&_fFontSmoothing, 0); _dwFontSmoothingType = FONT_SMOOTHING_AA; #ifdef CLEARTYPECOMBO if (SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, (PVOID)&_dwFontSmoothingType, 0)) { } #endif //CLEARTYPECOMBO // Show contents while dragging _fDragWindow = FALSE; SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, (PVOID)&_fDragWindow, 0); _fKeyboardIndicators = FALSE; SystemParametersInfo(SPI_GETKEYBOARDINDICATORS, 0, (PVOID)&_fKeyboardIndicators, 0); _fMenuShadows = TRUE; SystemParametersInfo(SPI_GETDROPSHADOW, 0, (PVOID)&_fMenuShadows, 0); // Set the old values so we know when they changed. _nOldLargeIcon = _nLargeIcon; _nOldHighIconColor = _nHighIconColor; _wpOldMenuAnimation = _wpMenuAnimation; _fOldFontSmoothing = _fFontSmoothing; _dwOldFontSmoothingType = _dwFontSmoothingType; _fOldDragWindow = _fDragWindow; _fOldKeyboardIndicators = _fKeyboardIndicators; _dwOldAnimationEffect = _dwAnimationEffect; _fOldMenuShadows = _fMenuShadows; // load the icons and add them to the image lists // get the icon files and indexes from the registry, including for the Default recycle bin for (int nIndex = 0; nIndex < ARRAYSIZE(_IconData); nIndex++) { TCHAR szTemp[MAX_PATH]; szTemp[0] = 0; IconGetRegValueString(c_aIconRegKeys[nIndex].pclsid, TEXT("DefaultIcon"), c_aIconRegKeys[nIndex].szIconValue, szTemp, ARRAYSIZE(szTemp)); int iIndex = PathParseIconLocation(szTemp); // store the icon information lstrcpy(_IconData[nIndex].szOldFile, szTemp); lstrcpy(_IconData[nIndex].szNewFile, szTemp); _IconData[nIndex].iOldIndex = iIndex; _IconData[nIndex].iNewIndex = iIndex; } return hr; } BOOL CEffectState::HasIconsChanged(IN CEffectState * pCurrent) { BOOL fHasIconsChanged = FALSE; int nIndex; for (nIndex = 0; nIndex < ARRAYSIZE(_IconData); nIndex++) { if (StrCmpI(_IconData[nIndex].szNewFile, pCurrent->_IconData[nIndex].szNewFile) || (_IconData[nIndex].iNewIndex != pCurrent->_IconData[nIndex].iNewIndex)) { fHasIconsChanged = TRUE; break; } } return fHasIconsChanged; } HRESULT CEffectState::Save(void) { HRESULT hr = S_OK; BOOL bDorked = FALSE; int iX; // Large Icons BOOL bSendSettingsChange = ChangeIconSizes(_nOldLargeIcon, _nLargeIcon); if (bSendSettingsChange) { _nOldLargeIcon = _nLargeIcon; bDorked = TRUE; } // Full Color Icons if(_nOldHighIconColor != _nHighIconColor) { SetRegValueInt(HKEY_CURRENT_USER, c_szHICKey, c_szHICVal, _nHighIconColor); if ((GetBitsPerPixel() < 16) && (_nHighIconColor == 16)) // Display mode won't support icon high colors { } else { _nOldHighIconColor = _nHighIconColor; bSendSettingsChange = TRUE; } } // Full window drag if (_fOldDragWindow != _fDragWindow) { _fOldDragWindow = _fDragWindow; SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, _fDragWindow, 0, SPIF_UPDATEINIFILE); // we need to send this because the tray's autohide switches off this bSendSettingsChange = TRUE; } // Show Menu Shadows if (_fOldMenuShadows != _fMenuShadows) { _fOldMenuShadows = _fMenuShadows; SystemParametersInfo(SPI_SETDROPSHADOW, _fMenuShadows, 0, SPIF_UPDATEINIFILE); // we need to send this because the tray's autohide switches off this bSendSettingsChange = TRUE; } // Font smoothing if ((_fOldFontSmoothing != _fFontSmoothing) || (_dwOldFontSmoothingType != _dwFontSmoothingType)) { #ifdef CLEARTYPECOMBO SystemParametersInfo(SPI_SETFONTSMOOTHINGTYPE, 0, (PVOID)UlongToPtr(_dwFontSmoothingType), SPIF_UPDATEINIFILE); #endif _dwOldFontSmoothingType = _dwFontSmoothingType; _fOldFontSmoothing = _fFontSmoothing; SystemParametersInfo(SPI_SETFONTSMOOTHING, _fFontSmoothing, 0, SPIF_UPDATEINIFILE); } // Menu animations if ((_wpOldMenuAnimation != _wpMenuAnimation) || (_dwOldAnimationEffect != _dwAnimationEffect)) { _wpOldMenuAnimation = _wpMenuAnimation; SetAnimations(_wpMenuAnimation, _dwAnimationEffect); _dwOldAnimationEffect = _dwAnimationEffect; } // Change the system icons for( iX = 0; iX < NUM_ICONS; iX++) { if ((lstrcmpi(_IconData[iX].szNewFile, _IconData[iX].szOldFile) != 0) || (_IconData[iX].iNewIndex != _IconData[iX].iOldIndex)) { TCHAR szTemp[MAX_PATH]; wnsprintf(szTemp, ARRAYSIZE(szTemp), TEXT("%s,%d"), _IconData[iX].szNewFile, _IconData[iX].iNewIndex); IconSetRegValueString(c_aIconRegKeys[iX].pclsid, TEXT("DefaultIcon"), c_aIconRegKeys[iX].szIconValue, szTemp); // Next two lines necessary if the user does an Apply as opposed to OK lstrcpy(_IconData[iX].szOldFile, _IconData[iX].szNewFile); _IconData[iX].iOldIndex = _IconData[iX].iNewIndex; bDorked = TRUE; } } // Keyboard indicators if (_fOldKeyboardIndicators != _fKeyboardIndicators) { _fOldKeyboardIndicators = _fKeyboardIndicators; DWORD_PTR dwResult; // Are we turning this on? (!_fKeyboardIndicators means "don't show" -> hide) if (!_fKeyboardIndicators) { // Yes, on: hide the key cues, turn on the mechanism SystemParametersInfo(SPI_SETKEYBOARDINDICATORS, 0, IntToPtr(_fKeyboardIndicators), SPIF_UPDATEINIFILE); SendMessageTimeout(HWND_BROADCAST, WM_CHANGEUISTATE, MAKEWPARAM(UIS_SET, UISF_HIDEFOCUS | UISF_HIDEACCEL), 0, SMTO_ABORTIFHUNG, 10*1000, &dwResult); } else { // No, off: means show the keycues, turn off the mechanism SendMessageTimeout(HWND_BROADCAST, WM_CHANGEUISTATE, MAKEWPARAM(UIS_CLEAR, UISF_HIDEFOCUS | UISF_HIDEACCEL), 0, SMTO_ABORTIFHUNG, 10*1000, &dwResult); SystemParametersInfo(SPI_SETKEYBOARDINDICATORS, 0, IntToPtr(_fKeyboardIndicators), SPIF_UPDATEINIFILE); } } // Make the system notice we changed the system icons if (bDorked) { PFNSHUPDATERECYCLEBINICON pfnSHUpdateRecycleBinIcon = NULL; SHChangeNotify(SHCNE_ASSOCCHANGED, 0, NULL, NULL); // should do the trick! if (!pfnSHUpdateRecycleBinIcon) { // Load SHUpdateRecycleBinIcon() if it exists g_hmodShell32 = LoadLibrary(SZ_SHELL32); pfnSHUpdateRecycleBinIcon = (PFNSHUPDATERECYCLEBINICON)GetProcAddress(g_hmodShell32, SZ_SHUPDATERECYCLEBINICON); } if (pfnSHUpdateRecycleBinIcon != NULL) { pfnSHUpdateRecycleBinIcon(); } } if (bSendSettingsChange) { DWORD_PTR dwResult = 0; SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, 0, SMTO_ABORTIFHUNG, 10*1000, &dwResult); } return hr; } #define SZ_ICON_DEFAULTICON L"DefaultValue" HRESULT CEffectState::GetIconPath(IN CLSID clsid, IN LPCWSTR pszName, IN LPWSTR pszPath, IN DWORD cchSize) { HRESULT hr = E_FAIL; int nIndex; if (!StrCmpIW(SZ_ICON_DEFAULTICON, pszName)) { pszName = L""; } for (nIndex = 0; nIndex < ARRAYSIZE(_IconData); nIndex++) { if (IsEqualCLSID(*(c_aIconRegKeys[nIndex].pclsid), clsid) && !StrCmpIW(pszName, c_aIconRegKeys[nIndex].szIconValue)) { // We found it. wnsprintfW(pszPath, cchSize, L"%s,%d", _IconData[nIndex].szNewFile, _IconData[nIndex].iNewIndex); hr = S_OK; break; } } return hr; } HRESULT CEffectState::SetIconPath(IN CLSID clsid, IN LPCWSTR pszName, IN LPCWSTR pszPath, IN int nResourceID) { HRESULT hr = E_FAIL; int nIndex; if (!StrCmpIW(SZ_ICON_DEFAULTICON, pszName)) { pszName = L""; } for (nIndex = 0; nIndex < ARRAYSIZE(_IconData); nIndex++) { if (IsEqualCLSID(*(c_aIconRegKeys[nIndex].pclsid), clsid) && !StrCmpIW(pszName, c_aIconRegKeys[nIndex].szIconValue)) { TCHAR szTemp[MAX_PATH]; if (!pszPath || !pszPath[0]) { // The caller didn't specify an icon so use the default values. if (!SHExpandEnvironmentStrings(c_aIconRegKeys[nIndex].szDefault, szTemp, ARRAYSIZE(szTemp))) { StrCpyN(szTemp, c_aIconRegKeys[nIndex].szDefault, ARRAYSIZE(szTemp)); } pszPath = szTemp; nResourceID = c_aIconRegKeys[nIndex].nDefaultIndex; } // We found it. StrCpyNW(_IconData[nIndex].szNewFile, pszPath, ARRAYSIZE(_IconData[nIndex].szNewFile)); _IconData[nIndex].iNewIndex = nResourceID; hr = S_OK; break; } } return hr; } HRESULT CEffectState::Clone(OUT CEffectState ** ppEffectClone) { HRESULT hr = E_OUTOFMEMORY; *ppEffectClone = new CEffectState(); if (*ppEffectClone) { hr = S_OK; (*ppEffectClone)->_nLargeIcon = _nLargeIcon; (*ppEffectClone)->_nHighIconColor = _nHighIconColor; (*ppEffectClone)->_wpMenuAnimation = _wpMenuAnimation; (*ppEffectClone)->_fFontSmoothing = _fFontSmoothing; (*ppEffectClone)->_dwFontSmoothingType = _dwFontSmoothingType; (*ppEffectClone)->_fDragWindow = _fDragWindow; (*ppEffectClone)->_fKeyboardIndicators = _fKeyboardIndicators; (*ppEffectClone)->_dwAnimationEffect = _dwAnimationEffect; (*ppEffectClone)->_nOldLargeIcon = _nOldLargeIcon; (*ppEffectClone)->_nOldHighIconColor = _nOldHighIconColor; (*ppEffectClone)->_wpOldMenuAnimation = _wpOldMenuAnimation; (*ppEffectClone)->_fOldFontSmoothing = _fOldFontSmoothing; (*ppEffectClone)->_dwOldFontSmoothingType = _dwOldFontSmoothingType; (*ppEffectClone)->_fOldDragWindow = _fOldDragWindow; (*ppEffectClone)->_fOldKeyboardIndicators = _fOldKeyboardIndicators; (*ppEffectClone)->_dwOldAnimationEffect = _dwOldAnimationEffect; (*ppEffectClone)->_fOldMenuShadows = _fOldMenuShadows; for (int nIndex = 0; nIndex < ARRAYSIZE(_IconData); nIndex++) { (*ppEffectClone)->_IconData[nIndex].iOldIndex = _IconData[nIndex].iOldIndex; (*ppEffectClone)->_IconData[nIndex].iNewIndex = _IconData[nIndex].iNewIndex; StrCpyN((*ppEffectClone)->_IconData[nIndex].szOldFile, _IconData[nIndex].szOldFile, ARRAYSIZE((*ppEffectClone)->_IconData[nIndex].szOldFile)); StrCpyN((*ppEffectClone)->_IconData[nIndex].szNewFile, _IconData[nIndex].szNewFile, ARRAYSIZE((*ppEffectClone)->_IconData[nIndex].szNewFile)); } } return hr; } BOOL CEffectState::IsDirty(void) { BOOL fDirty = FALSE; if ((_nLargeIcon != _nOldLargeIcon) || (_nHighIconColor != _nOldHighIconColor) || (_wpMenuAnimation != _wpOldMenuAnimation) || (_fFontSmoothing != _fOldFontSmoothing) || (_dwFontSmoothingType != _dwOldFontSmoothingType) || (_fDragWindow != _fOldDragWindow) || (_fMenuShadows != _fOldMenuShadows) || (_fKeyboardIndicators != _fOldKeyboardIndicators) || (_dwAnimationEffect != _dwOldAnimationEffect)) { fDirty = TRUE; } else { for (int nIndex = 0; nIndex < ARRAYSIZE(_IconData); nIndex++) { if ((_IconData[nIndex].iNewIndex != _IconData[nIndex].iOldIndex) || (StrCmpI(_IconData[nIndex].szNewFile, _IconData[nIndex].szOldFile))) { fDirty = TRUE; break; } } } return fDirty; }