From 0f94e03b4013b42246c7df6ba5e8c6c6a8985fcd Mon Sep 17 00:00:00 2001 From: Frank Richter Date: Fri, 12 Aug 2005 15:51:13 +0000 Subject: [PATCH] Enhance uxtheme to store the themed system metrics in the registry and also backup the old metrics. That way, themed system colors are set even uxtheme was not loaded and initialized yet, and when a theme is deactivated, the colors prior to the activation are restored as well. Also, not having to set the system colors in uxtheme startup works around weird problems where SetSystemColors() ended up being called from inside window creation and this seemingly led to some creation message being sent twice. --- dlls/uxtheme/msstyles.c | 12 +-- dlls/uxtheme/msstyles.h | 2 +- dlls/uxtheme/system.c | 209 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 213 insertions(+), 10 deletions(-) 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)) {