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.
This commit is contained in:
parent
d4441f2817
commit
0f94e03b40
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "config.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#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)) {
|
||||
|
|
Loading…
Reference in New Issue