[PATCH] UXTHEME: Set non-client metrics from theme

Frank Richter frank.richter at gmail.com
Mon Aug 14 12:22:18 CDT 2006



-------------- next part --------------
>From f8d4f796e734aebb430546495020f897f3518728 Mon Sep 17 00:00:00 2001
From: Frank Richter frank.richter at gmail.com <frank.richter at gmail.com>
Date: Mon, 14 Aug 2006 19:20:48 +0200
Subject: [PATCH] UXTHEME: Set non-client metrics from theme
---
 dlls/uxtheme/msstyles.c |  177 +++++++++++++++++++++++++++++++++++++++++++++--
 dlls/uxtheme/system.c   |   67 +++++++++++++++++-
 2 files changed, 233 insertions(+), 11 deletions(-)

diff --git a/dlls/uxtheme/msstyles.c b/dlls/uxtheme/msstyles.c
index 4649a36..9225206 100644
--- a/dlls/uxtheme/msstyles.c
+++ b/dlls/uxtheme/msstyles.c
@@ -25,9 +25,9 @@ #include <stdlib.h>
 
 #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 PA
 	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 
     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 
 			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 
                     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
  *
  * 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_
     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_
         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 e19f913..b115c53 100644
--- a/dlls/uxtheme/system.c
+++ b/dlls/uxtheme/system.c
@@ -25,8 +25,8 @@ #include <stdio.h>
 
 #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(
                          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(
         
             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
             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(vo
     
         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);
 }
 
 /***********************************************************************
-- 
1.4.1.1



More information about the wine-patches mailing list