diff --git a/dlls/uxtheme/msstyles.c b/dlls/uxtheme/msstyles.c index e1e20d6664c..65633f19941 100644 --- a/dlls/uxtheme/msstyles.c +++ b/dlls/uxtheme/msstyles.c @@ -45,7 +45,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(uxtheme); BOOL MSSTYLES_GetNextInteger(LPCWSTR lpStringStart, LPCWSTR lpStringEnd, LPCWSTR *lpValEnd, int *value); BOOL MSSTYLES_GetNextToken(LPCWSTR lpStringStart, LPCWSTR lpStringEnd, LPCWSTR *lpValEnd, LPWSTR lpBuff, DWORD buffSize); -void MSSTYLES_ParseThemeIni(PTHEME_FILE tf); +void MSSTYLES_ParseThemeIni(PTHEME_FILE tf, BOOL setMetrics); extern HINSTANCE hDllInst; @@ -224,7 +224,7 @@ void MSSTYLES_CloseThemeFile(PTHEME_FILE tf) * * Set the current active theme */ -HRESULT MSSTYLES_SetActiveTheme(PTHEME_FILE tf) +HRESULT MSSTYLES_SetActiveTheme(PTHEME_FILE tf, BOOL setMetrics) { if(tfActiveTheme) MSSTYLES_CloseThemeFile(tfActiveTheme); @@ -233,7 +233,7 @@ HRESULT MSSTYLES_SetActiveTheme(PTHEME_FILE tf) { tfActiveTheme->dwRefCount++; if(!tfActiveTheme->classes) - MSSTYLES_ParseThemeIni(tfActiveTheme); + MSSTYLES_ParseThemeIni(tfActiveTheme, setMetrics); } return S_OK; } @@ -664,7 +664,7 @@ static PTHEME_PROPERTY MSSTYLES_AddMetric(PTHEME_FILE tf, int iPropertyPrimitive * PARAMS * tf Theme to parse */ -void MSSTYLES_ParseThemeIni(PTHEME_FILE tf) +void MSSTYLES_ParseThemeIni(PTHEME_FILE tf, BOOL setMetrics) { static const WCHAR szSysMetrics[] = {'S','y','s','M','e','t','r','i','c','s','\0'}; static const WCHAR szGlobals[] = {'g','l','o','b','a','l','s','\0'}; @@ -709,7 +709,7 @@ void MSSTYLES_ParseThemeIni(PTHEME_FILE tf) FIXME("Invalid color value for %s\n", debugstr_w(szPropertyName)); } } - else if (iPropertyId == TMT_FLATMENUS) { + else if (setMetrics && (iPropertyId == TMT_FLATMENUS)) { BOOL flatMenus = (*lpValue == 'T') || (*lpValue == 't'); SystemParametersInfoW (SPI_SETFLATMENU, 0, (PVOID)flatMenus, 0); } @@ -720,7 +720,7 @@ void MSSTYLES_ParseThemeIni(PTHEME_FILE tf) TRACE("Unknown system metric %s\n", debugstr_w(szPropertyName)); } } - if(colorCount > 0) + if (setMetrics && (colorCount > 0)) SetSysColors(colorCount, colorElements, colorRgb); continue; } diff --git a/dlls/uxtheme/msstyles.h b/dlls/uxtheme/msstyles.h index 93e3cd0b5a3..4767d4cf970 100644 --- a/dlls/uxtheme/msstyles.h +++ b/dlls/uxtheme/msstyles.h @@ -77,7 +77,7 @@ typedef void* PUXINI_FILE; HRESULT MSSTYLES_OpenThemeFile(LPCWSTR lpThemeFile, LPCWSTR pszColorName, LPCWSTR pszSizeName, PTHEME_FILE *tf); void MSSTYLES_CloseThemeFile(PTHEME_FILE tf); -HRESULT MSSTYLES_SetActiveTheme(PTHEME_FILE tf); +HRESULT MSSTYLES_SetActiveTheme(PTHEME_FILE tf, BOOL setMetrics); PTHEME_CLASS MSSTYLES_OpenThemeClass(LPCWSTR pszAppName, LPCWSTR pszClassList); HRESULT MSSTYLES_CloseThemeClass(PTHEME_CLASS tc); BOOL MSSTYLES_LookupProperty(LPCWSTR pszPropertyName, int *dwPrimitive, int *dwId); diff --git a/dlls/uxtheme/system.c b/dlls/uxtheme/system.c index 2a5837f0f07..9aeede82ee0 100644 --- a/dlls/uxtheme/system.c +++ b/dlls/uxtheme/system.c @@ -21,6 +21,7 @@ #include "config.h" #include +#include #include "windef.h" #include "winbase.h" @@ -146,18 +147,210 @@ static void UXTHEME_LoadTheme(void) lstrcpynW(szCurrentColor, pt->pszSelectedColor, sizeof(szCurrentColor)/sizeof(szCurrentColor[0])); lstrcpynW(szCurrentSize, pt->pszSelectedSize, sizeof(szCurrentSize)/sizeof(szCurrentSize[0])); - MSSTYLES_SetActiveTheme(pt); + MSSTYLES_SetActiveTheme(pt, FALSE); TRACE("Theme active: %s %s %s\n", debugstr_w(szCurrentTheme), debugstr_w(szCurrentColor), debugstr_w(szCurrentSize)); MSSTYLES_CloseThemeFile(pt); } } if(!bThemeActive) { - MSSTYLES_SetActiveTheme(NULL); + MSSTYLES_SetActiveTheme(NULL, FALSE); TRACE("Themeing not active\n"); } } +/***********************************************************************/ + +static const char * const SysColorsNames[] = +{ + "Scrollbar", /* COLOR_SCROLLBAR */ + "Background", /* COLOR_BACKGROUND */ + "ActiveTitle", /* COLOR_ACTIVECAPTION */ + "InactiveTitle", /* COLOR_INACTIVECAPTION */ + "Menu", /* COLOR_MENU */ + "Window", /* COLOR_WINDOW */ + "WindowFrame", /* COLOR_WINDOWFRAME */ + "MenuText", /* COLOR_MENUTEXT */ + "WindowText", /* COLOR_WINDOWTEXT */ + "TitleText", /* COLOR_CAPTIONTEXT */ + "ActiveBorder", /* COLOR_ACTIVEBORDER */ + "InactiveBorder", /* COLOR_INACTIVEBORDER */ + "AppWorkSpace", /* COLOR_APPWORKSPACE */ + "Hilight", /* COLOR_HIGHLIGHT */ + "HilightText", /* COLOR_HIGHLIGHTTEXT */ + "ButtonFace", /* COLOR_BTNFACE */ + "ButtonShadow", /* COLOR_BTNSHADOW */ + "GrayText", /* COLOR_GRAYTEXT */ + "ButtonText", /* COLOR_BTNTEXT */ + "InactiveTitleText", /* COLOR_INACTIVECAPTIONTEXT */ + "ButtonHilight", /* COLOR_BTNHIGHLIGHT */ + "ButtonDkShadow", /* COLOR_3DDKSHADOW */ + "ButtonLight", /* COLOR_3DLIGHT */ + "InfoText", /* COLOR_INFOTEXT */ + "InfoWindow", /* COLOR_INFOBK */ + "ButtonAlternateFace", /* COLOR_ALTERNATEBTNFACE */ + "HotTrackingColor", /* COLOR_HOTLIGHT */ + "GradientActiveTitle", /* COLOR_GRADIENTACTIVECAPTION */ + "GradientInactiveTitle", /* COLOR_GRADIENTINACTIVECAPTION */ + "MenuHilight", /* COLOR_MENUHILIGHT */ + "MenuBar", /* COLOR_MENUBAR */ +}; +static const WCHAR strColorKey[] = + { 'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\', + 'C','o','l','o','r','s',0 }; +static const WCHAR keyFlatMenus[] = { 'F','l','a','t','M','e','n','u', 0}; + +static const struct BackupSysParam +{ + int spiGet, spiSet; + const WCHAR* keyName; +} backupSysParams[] = +{ + {SPI_GETFLATMENU, SPI_SETFLATMENU, keyFlatMenus}, + {-1, -1, 0} +}; + +#define NUM_SYS_COLORS (COLOR_MENUBAR+1) + +static void save_sys_colors (HKEY baseKey) +{ + char colorStr[13]; + HKEY hKey; + int i; + + if (RegCreateKeyExW( baseKey, strColorKey, + 0, 0, 0, KEY_ALL_ACCESS, + 0, &hKey, 0 ) == ERROR_SUCCESS) + { + for (i = 0; i < NUM_SYS_COLORS; i++) + { + COLORREF col = GetSysColor (i); + + sprintf (colorStr, "%d %d %d", + GetRValue (col), GetGValue (col), GetBValue (col)); + + RegSetValueExA (hKey, SysColorsNames[i], 0, REG_SZ, + (BYTE*)colorStr, strlen (colorStr)+1); + } + RegCloseKey (hKey); + } +} + +/* Before activating a theme, query current system colors, certain settings + * and backup them in the registry, so they can be restored when the theme + * is deactivated */ +static void UXTHEME_BackupSystemMetrics(void) +{ + HKEY hKey; + const struct BackupSysParam* bsp = backupSysParams; + + if (RegCreateKeyExW( HKEY_CURRENT_USER, szThemeManager, + 0, 0, 0, KEY_ALL_ACCESS, + 0, &hKey, 0) == ERROR_SUCCESS) + { + save_sys_colors (hKey); + + while (bsp->spiGet >= 0) + { + DWORD value; + + SystemParametersInfoW (bsp->spiGet, 0, &value, 0); + RegSetValueExW (hKey, bsp->keyName, 0, REG_DWORD, + (LPBYTE)&value, sizeof (value)); + + bsp++; + } + + RegCloseKey (hKey); + } +} + +/* Read back old settings after a theme was deactivated */ +static void UXTHEME_RestoreSystemMetrics(void) +{ + HKEY hKey; + const struct BackupSysParam* bsp = backupSysParams; + + if (RegOpenKeyExW (HKEY_CURRENT_USER, szThemeManager, + 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) + { + HKEY colorKey; + + /* read backed-up colors */ + if (RegOpenKeyExW (hKey, strColorKey, + 0, KEY_QUERY_VALUE, &colorKey) == ERROR_SUCCESS) + { + int i; + COLORREF sysCols[NUM_SYS_COLORS]; + int sysColsIndices[NUM_SYS_COLORS]; + int sysColCount = 0; + + for (i = 0; i < NUM_SYS_COLORS; i++) + { + DWORD type; + char colorStr[13]; + DWORD count = sizeof(colorStr); + + if (SUCCEEDED(RegQueryValueExA (colorKey, SysColorsNames[i], 0, + &type, colorStr, &count))) + { + int r, g, b; + if (sscanf (colorStr, "%d %d %d", &r, &g, &b) == 3) + { + sysColsIndices[sysColCount] = i; + sysCols[sysColCount] = RGB(r, g, b); + sysColCount++; + } + } + } + RegCloseKey (colorKey); + + SetSysColors (sysColCount, sysColsIndices, sysCols); + } + + /* read backed-up other settings */ + while (bsp->spiGet >= 0) + { + DWORD value; + DWORD count = sizeof(value); + DWORD type; + + if (SUCCEEDED(RegQueryValueExW (hKey, bsp->keyName, 0, + &type, (LPBYTE)&value, &count))) + { + SystemParametersInfoW (bsp->spiSet, 0, (LPVOID)value, + SPIF_UPDATEINIFILE); + } + + bsp++; + } + + + RegCloseKey (hKey); + } +} + +/* Make system settings persistent, so they're in effect even w/o uxtheme + * loaded */ +static void UXTHEME_SaveSystemMetrics(void) +{ + const struct BackupSysParam* bsp = backupSysParams; + + save_sys_colors (HKEY_CURRENT_USER); + + while (bsp->spiGet >= 0) + { + DWORD value; + + SystemParametersInfoW (bsp->spiGet, 0, &value, 0); + SystemParametersInfoW (bsp->spiSet, 0, (LPVOID)value, + SPIF_UPDATEINIFILE); + + bsp++; + } + +} + /*********************************************************************** * UXTHEME_SetActiveTheme * @@ -169,7 +362,8 @@ HRESULT UXTHEME_SetActiveTheme(PTHEME_FILE tf) WCHAR tmp[2]; HRESULT hr; - hr = MSSTYLES_SetActiveTheme(tf); + if(tf) UXTHEME_BackupSystemMetrics(); + hr = MSSTYLES_SetActiveTheme(tf, TRUE); if(FAILED(hr)) return hr; if(tf) { @@ -179,6 +373,7 @@ HRESULT UXTHEME_SetActiveTheme(PTHEME_FILE tf) lstrcpynW(szCurrentSize, tf->pszSelectedSize, sizeof(szCurrentSize)/sizeof(szCurrentSize[0])); } else { + UXTHEME_RestoreSystemMetrics(); bThemeActive = FALSE; szCurrentTheme[0] = '\0'; szCurrentColor[0] = '\0'; @@ -208,6 +403,9 @@ HRESULT UXTHEME_SetActiveTheme(PTHEME_FILE tf) } else TRACE("Failed to open theme registry key\n"); + + UXTHEME_SaveSystemMetrics (); + return hr; } @@ -270,6 +468,11 @@ HRESULT WINAPI EnableTheming(BOOL fEnable) TRACE("(%d)\n", fEnable); if(fEnable != bThemeActive) { + if(fEnable) + UXTHEME_BackupSystemMetrics(); + else + UXTHEME_RestoreSystemMetrics(); + UXTHEME_SaveSystemMetrics (); bThemeActive = fEnable; if(bThemeActive) szEnabled[0] = '1'; if(!RegOpenKeyW(HKEY_CURRENT_USER, szThemeManager, &hKey)) {