diff --git a/dlls/uxtheme/msstyles.c b/dlls/uxtheme/msstyles.c index 4649a36dd9c..9225206d002 100644 --- a/dlls/uxtheme/msstyles.c +++ b/dlls/uxtheme/msstyles.c @@ -25,9 +25,9 @@ #include "windef.h" #include "winbase.h" +#include "wingdi.h" #include "winuser.h" #include "winnls.h" -#include "wingdi.h" #include "uxtheme.h" #include "tmschema.h" @@ -46,6 +46,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, BOOL setMetrics); +HRESULT MSSTYLES_GetFont (LPCWSTR lpStringStart, LPCWSTR lpStringEnd, LPCWSTR *lpValEnd, LOGFONTW* logfont); extern HINSTANCE hDllInst; extern int alphaBlendMode; @@ -719,6 +720,130 @@ static void parse_apply_color (struct PARSECOLORSTATE* state) SystemParametersInfoW (SPI_SETGRADIENTCAPTIONS, 0, (PVOID)TRUE, 0); } +/* Non-client-metrics-related state for theme ini parsing */ +struct PARSENONCLIENTSTATE +{ + NONCLIENTMETRICSW metrics; + BOOL metricsDirty; + LOGFONTW iconTitleFont; +}; + +inline void parse_init_nonclient (struct PARSENONCLIENTSTATE* state) +{ + memset (state, 0, sizeof (*state)); + state->metrics.cbSize = sizeof (NONCLIENTMETRICSW); + SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, sizeof (NONCLIENTMETRICSW), + (PVOID)&state->metrics, 0); + SystemParametersInfoW (SPI_GETICONTITLELOGFONT, sizeof (LOGFONTW), + (PVOID)&state->iconTitleFont, 0); +} + +static BOOL parse_handle_nonclient_font (struct PARSENONCLIENTSTATE* state, + int iPropertyId, LPCWSTR lpValue, + DWORD dwValueLen) +{ + LOGFONTW font; + + memset (&font, 0, sizeof (font)); + if (SUCCEEDED (MSSTYLES_GetFont (lpValue, lpValue + dwValueLen, &lpValue, + &font))) + { + switch (iPropertyId) + { + case TMT_CAPTIONFONT: + memcpy (&state->metrics.lfCaptionFont, &font, sizeof (LOGFONTW)); + state->metricsDirty = TRUE; + break; + case TMT_SMALLCAPTIONFONT: + memcpy (&state->metrics.lfSmCaptionFont, &font, sizeof (LOGFONTW)); + state->metricsDirty = TRUE; + break; + case TMT_MENUFONT: + memcpy (&state->metrics.lfMenuFont, &font, sizeof (LOGFONTW)); + state->metricsDirty = TRUE; + break; + case TMT_STATUSFONT: + memcpy (&state->metrics.lfStatusFont, &font, sizeof (LOGFONTW)); + state->metricsDirty = TRUE; + break; + case TMT_MSGBOXFONT: + memcpy (&state->metrics.lfMessageFont, &font, sizeof (LOGFONTW)); + state->metricsDirty = TRUE; + break; + case TMT_ICONTITLEFONT: + memcpy (&state->iconTitleFont, &font, sizeof (LOGFONTW)); + state->metricsDirty = TRUE; + break; + } + return TRUE; + } + else + return FALSE; +} + +static BOOL parse_handle_nonclient_size (struct PARSENONCLIENTSTATE* state, + int iPropertyId, LPCWSTR lpValue, + DWORD dwValueLen) +{ + int size; + LPCWSTR lpValueEnd = lpValue + dwValueLen; + if(MSSTYLES_GetNextInteger(lpValue, lpValueEnd, &lpValue, &size)) { + switch (iPropertyId) + { + case TMT_SIZINGBORDERWIDTH: + state->metrics.iBorderWidth = size; + state->metricsDirty = TRUE; + break; + case TMT_SCROLLBARWIDTH: + state->metrics.iScrollWidth = size; + state->metricsDirty = TRUE; + break; + case TMT_SCROLLBARHEIGHT: + state->metrics.iScrollHeight = size; + state->metricsDirty = TRUE; + break; + case TMT_CAPTIONBARWIDTH: + state->metrics.iCaptionWidth = size; + state->metricsDirty = TRUE; + break; + case TMT_CAPTIONBARHEIGHT: + state->metrics.iCaptionHeight = size; + state->metricsDirty = TRUE; + break; + case TMT_SMCAPTIONBARWIDTH: + state->metrics.iSmCaptionWidth = size; + state->metricsDirty = TRUE; + break; + case TMT_SMCAPTIONBARHEIGHT: + state->metrics.iSmCaptionHeight = size; + state->metricsDirty = TRUE; + break; + case TMT_MENUBARWIDTH: + state->metrics.iMenuWidth = size; + state->metricsDirty = TRUE; + break; + case TMT_MENUBARHEIGHT: + state->metrics.iMenuHeight = size; + state->metricsDirty = TRUE; + break; + } + return TRUE; + } + else + return FALSE; +} + +static void parse_apply_nonclient (struct PARSENONCLIENTSTATE* state) +{ + if (state->metricsDirty) + { + SystemParametersInfoW (SPI_SETNONCLIENTMETRICS, sizeof (state->metrics), + (PVOID)&state->metrics, 0); + SystemParametersInfoW (SPI_SETICONTITLELOGFONT, sizeof (state->iconTitleFont), + (PVOID)&state->iconTitleFont, 0); + } +} + /*********************************************************************** * MSSTYLES_ParseThemeIni * @@ -752,8 +877,10 @@ void MSSTYLES_ParseThemeIni(PTHEME_FILE tf, BOOL setMetrics) while((lpName=UXINI_GetNextSection(ini, &dwLen))) { if(CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, lpName, dwLen, szSysMetrics, -1) == CSTR_EQUAL) { struct PARSECOLORSTATE colorState; + struct PARSENONCLIENTSTATE nonClientState; parse_init_color (&colorState); + parse_init_nonclient (&nonClientState); while((lpName=UXINI_GetNextValue(ini, &dwLen, &lpValue, &dwValueLen))) { lstrcpynW(szPropertyName, lpName, min(dwLen+1, sizeof(szPropertyName)/sizeof(szPropertyName[0]))); @@ -768,6 +895,22 @@ void MSSTYLES_ParseThemeIni(PTHEME_FILE tf, BOOL setMetrics) BOOL flatMenus = (*lpValue == 'T') || (*lpValue == 't'); SystemParametersInfoW (SPI_SETFLATMENU, 0, (PVOID)(INT_PTR)flatMenus, 0); } + else if ((iPropertyId >= TMT_FIRSTFONT) + && (iPropertyId <= TMT_LASTFONT)) + { + if (!parse_handle_nonclient_font (&nonClientState, + iPropertyId, lpValue, dwValueLen)) + FIXME("Invalid font value for %s\n", + debugstr_w(szPropertyName)); + } + else if ((iPropertyId >= TMT_FIRSTSIZE) + && (iPropertyId <= TMT_LASTSIZE)) + { + if (!parse_handle_nonclient_size (&nonClientState, + iPropertyId, lpValue, dwValueLen)) + FIXME("Invalid size value for %s\n", + debugstr_w(szPropertyName)); + } /* Catch all metrics, including colors */ MSSTYLES_AddMetric(tf, iPropertyPrimitive, iPropertyId, lpValue, dwValueLen); } @@ -775,7 +918,11 @@ void MSSTYLES_ParseThemeIni(PTHEME_FILE tf, BOOL setMetrics) TRACE("Unknown system metric %s\n", debugstr_w(szPropertyName)); } } - if (setMetrics) parse_apply_color (&colorState); + if (setMetrics) + { + parse_apply_color (&colorState); + parse_apply_nonclient (&nonClientState); + } continue; } if(MSSTYLES_ParseIniSectionName(lpName, dwLen, szAppName, szClassName, &iPartId, &iStateId)) { @@ -1078,7 +1225,8 @@ HRESULT MSSTYLES_GetPropertyColor(PTHEME_PROPERTY tp, COLORREF *pColor) * * Retrieve a color value for a property */ -HRESULT MSSTYLES_GetPropertyFont(PTHEME_PROPERTY tp, HDC hdc, LOGFONTW *pFont) +HRESULT MSSTYLES_GetFont (LPCWSTR lpCur, LPCWSTR lpEnd, + LPCWSTR *lpValEnd, LOGFONTW* pFont) { static const WCHAR szBold[] = {'b','o','l','d','\0'}; static const WCHAR szItalic[] = {'i','t','a','l','i','c','\0'}; @@ -1086,20 +1234,18 @@ HRESULT MSSTYLES_GetPropertyFont(PTHEME_PROPERTY tp, HDC hdc, LOGFONTW *pFont) static const WCHAR szStrikeOut[] = {'s','t','r','i','k','e','o','u','t','\0'}; int pointSize; WCHAR attr[32]; - LPCWSTR lpCur = tp->lpValue; - LPCWSTR lpEnd = tp->lpValue + tp->dwValueLen; - - ZeroMemory(pFont, sizeof(LOGFONTW)); if(!MSSTYLES_GetNextToken(lpCur, lpEnd, &lpCur, pFont->lfFaceName, LF_FACESIZE)) { TRACE("Property is there, but failed to get face name\n"); + *lpValEnd = lpCur; return E_PROP_ID_UNSUPPORTED; } if(!MSSTYLES_GetNextInteger(lpCur, lpEnd, &lpCur, &pointSize)) { TRACE("Property is there, but failed to get point size\n"); + *lpValEnd = lpCur; return E_PROP_ID_UNSUPPORTED; } - pFont->lfHeight = -MulDiv(pointSize, GetDeviceCaps(hdc, LOGPIXELSY), 72); + pFont->lfHeight = pointSize; pFont->lfWeight = FW_REGULAR; pFont->lfCharSet = DEFAULT_CHARSET; while(MSSTYLES_GetNextToken(lpCur, lpEnd, &lpCur, attr, sizeof(attr)/sizeof(attr[0]))) { @@ -1108,9 +1254,24 @@ HRESULT MSSTYLES_GetPropertyFont(PTHEME_PROPERTY tp, HDC hdc, LOGFONTW *pFont) else if(!!lstrcmpiW(szUnderline, attr)) pFont->lfUnderline = TRUE; else if(!!lstrcmpiW(szStrikeOut, attr)) pFont->lfStrikeOut = TRUE; } + *lpValEnd = lpCur; return S_OK; } +HRESULT MSSTYLES_GetPropertyFont(PTHEME_PROPERTY tp, HDC hdc, LOGFONTW *pFont) +{ + LPCWSTR lpCur = tp->lpValue; + LPCWSTR lpEnd = tp->lpValue + tp->dwValueLen; + HRESULT hr; + + ZeroMemory(pFont, sizeof(LOGFONTW)); + hr = MSSTYLES_GetFont (lpCur, lpEnd, &lpCur, pFont); + if (SUCCEEDED (hr)) + pFont->lfHeight = -MulDiv(pFont->lfHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72); + + return hr; +} + /*********************************************************************** * MSSTYLES_GetPropertyInt * diff --git a/dlls/uxtheme/system.c b/dlls/uxtheme/system.c index e19f91344dc..b115c536a6e 100644 --- a/dlls/uxtheme/system.c +++ b/dlls/uxtheme/system.c @@ -25,8 +25,8 @@ #include "windef.h" #include "winbase.h" -#include "winuser.h" #include "wingdi.h" +#include "winuser.h" #include "winreg.h" #include "uxtheme.h" #include "tmschema.h" @@ -251,6 +251,10 @@ static const WCHAR strColorKey[] = static const WCHAR keyFlatMenus[] = { 'F','l','a','t','M','e','n','u', 0}; static const WCHAR keyGradientCaption[] = { 'G','r','a','d','i','e','n','t', 'C','a','p','t','i','o','n', 0 }; +static const WCHAR keyNonClientMetrics[] = { 'N','o','n','C','l','i','e','n','t', + 'M','e','t','r','i','c','s',0 }; +static const WCHAR keyIconTitleFont[] = { 'I','c','o','n','T','i','t','l','e', + 'F','o','n','t',0 }; static const struct BackupSysParam { @@ -301,8 +305,13 @@ static void UXTHEME_BackupSystemMetrics(void) 0, 0, 0, KEY_ALL_ACCESS, 0, &hKey, 0) == ERROR_SUCCESS) { + NONCLIENTMETRICSW ncm; + LOGFONTW iconTitleFont; + + /* back up colors */ save_sys_colors (hKey); + /* back up "other" settings */ while (bsp->spiGet >= 0) { DWORD value; @@ -313,6 +322,18 @@ static void UXTHEME_BackupSystemMetrics(void) bsp++; } + + /* back up non-client metrics */ + memset (&ncm, 0, sizeof (ncm)); + ncm.cbSize = sizeof (ncm); + SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, sizeof (ncm), &ncm, 0); + RegSetValueExW (hKey, keyNonClientMetrics, 0, REG_BINARY, (LPBYTE)&ncm, + sizeof (ncm)); + memset (&iconTitleFont, 0, sizeof (iconTitleFont)); + SystemParametersInfoW (SPI_GETICONTITLELOGFONT, sizeof (iconTitleFont), + &iconTitleFont, 0); + RegSetValueExW (hKey, keyIconTitleFont, 0, REG_BINARY, + (LPBYTE)&iconTitleFont, sizeof (iconTitleFont)); RegCloseKey (hKey); } @@ -378,16 +399,43 @@ static void UXTHEME_RestoreSystemMetrics(void) bsp++; } + /* read backed-up non-client metrics */ + { + NONCLIENTMETRICSW ncm; + LOGFONTW iconTitleFont; + DWORD count = sizeof(ncm); + DWORD type; + + if (RegQueryValueExW (hKey, keyNonClientMetrics, 0, + &type, (LPBYTE)&ncm, &count) == ERROR_SUCCESS) + { + SystemParametersInfoW (SPI_SETNONCLIENTMETRICS, + count, (LPVOID)&ncm, SPIF_UPDATEINIFILE); + } + + count = sizeof(iconTitleFont); + + if (RegQueryValueExW (hKey, keyIconTitleFont, 0, + &type, (LPBYTE)&iconTitleFont, &count) == ERROR_SUCCESS) + { + SystemParametersInfoW (SPI_SETICONTITLELOGFONT, + count, (LPVOID)&iconTitleFont, SPIF_UPDATEINIFILE); + } + } RegCloseKey (hKey); } } /* Make system settings persistent, so they're in effect even w/o uxtheme - * loaded */ + * loaded. + * For efficiency reasons, only the last SystemParametersInfoW sets + * SPIF_SENDWININICHANGE */ static void UXTHEME_SaveSystemMetrics(void) { const struct BackupSysParam* bsp = backupSysParams; + NONCLIENTMETRICSW ncm; + LOGFONTW iconTitleFont; save_sys_colors (HKEY_CURRENT_USER); @@ -401,7 +449,20 @@ static void UXTHEME_SaveSystemMetrics(void) bsp++; } + + memset (&ncm, 0, sizeof (ncm)); + ncm.cbSize = sizeof (ncm); + SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, + sizeof (ncm), (LPVOID)&ncm, 0); + SystemParametersInfoW (SPI_SETNONCLIENTMETRICS, + sizeof (ncm), (LPVOID)&ncm, SPIF_UPDATEINIFILE); + memset (&iconTitleFont, 0, sizeof (iconTitleFont)); + SystemParametersInfoW (SPI_GETICONTITLELOGFONT, + sizeof (iconTitleFont), (LPVOID)&iconTitleFont, 0); + SystemParametersInfoW (SPI_SETICONTITLELOGFONT, + sizeof (iconTitleFont), (LPVOID)&iconTitleFont, + SPIF_UPDATEINIFILE | SPIF_SENDCHANGE); } /***********************************************************************