Sync to Wine-20050725:
Thomas Weidenmueller <wine-patches@reactsoft.com>
- IsThemeDialogTextureEnabled should have one parameter to match the
  prototype in the official headers.
Mike McCormack <mike@codeweavers.com>
- gcc 4.0 -Wpointer-sign fixes (Reg* functions).
Stefan Huehner <stefan@huehner.org>
- Make some function static.
- Fix -Wmissing-declarations warnings.
Frank Richter <frank.richter@gmail.com>
- Enable/disable "flat menus" based on the setting from the active
  theme.
- Have the theme INI file parsed upon theme activation and not just when
  the first theme data is requested; that way, the themed system colors
  are set correctly from the start, and not just after some theme data
  was requested.
- GetThemeBackgroundContentRect() does not use the content margins
  alone, it also falls back to the border size or sizing margins, and if
  it can't find any possible margins at all, it returns the original
  rectangle.
- Make dialog theme texture setting non-global (ie a per-window
  setting).
- Better viewport origin in DrawThemeParentBackground().
- OpenThemeData() now always sets the window theme to the handle
  returned (even if that is NULL) - previously, it could happen that
  when no theme was active or the theme data could not be opened that
  the window theme remained became then-dangling (and hence subsequent
  calls to GetWindowTheme() would return that bogus theme).
- Correct border rectangle drawing.
- Don't crash if NULL is passed as the class list to OpenThemeData().
- UXTHEME_LoadImage(): Set default image count to 1 to avoid division by
  zero in case image count property is not given. Properly support 0
  state IDs.
- Every window needs to receive WM_THEMECHANGED (esp. controls), so also
  send it to child windows.
- Changed the default transparent color in case none was explicitly
  specified from the upper left pixel color to magenta. Empirically
  gives better results.
- Write WCHAR strings to registry with correct size.
- Opening some theme class data now also increases the reference count
  of the theme file, so as long as theme class data is still opened
  somewhere, the theme file won't get freed. Otherwise, it could happen
  that invalid class data was used, which could lead to problems.
Modified: trunk/reactos/lib/uxtheme/draw.c
Modified: trunk/reactos/lib/uxtheme/msstyles.c
Modified: trunk/reactos/lib/uxtheme/msstyles.h
Modified: trunk/reactos/lib/uxtheme/system.c

Modified: trunk/reactos/lib/uxtheme/draw.c
--- trunk/reactos/lib/uxtheme/draw.c	2005-08-12 18:17:37 UTC (rev 17341)
+++ trunk/reactos/lib/uxtheme/draw.c	2005-08-12 18:22:47 UTC (rev 17342)
@@ -41,7 +41,7 @@
  * Defines and global variables
  */
 
-DWORD dwDialogTextureFlags;
+extern ATOM atDialogThemeEnabled;
 
 /***********************************************************************/
 
@@ -50,8 +50,19 @@
  */
 HRESULT WINAPI EnableThemeDialogTexture(HWND hwnd, DWORD dwFlags)
 {
+    static const WCHAR szTab[] = { 'T','a','b',0 };
+    HRESULT hr;
+
     TRACE("(%p,0x%08lx\n", hwnd, dwFlags);
-    dwDialogTextureFlags = dwFlags;
+    hr = SetPropW (hwnd, MAKEINTATOMW (atDialogThemeEnabled), 
+        (HANDLE)(dwFlags|0x80000000)); 
+        /* 0x80000000 serves as a "flags set" flag */
+    if (FAILED(hr))
+          return hr;
+    if (dwFlags & ETDT_USETABTEXTURE)
+        return SetWindowTheme (hwnd, NULL, szTab);
+    else
+        return SetWindowTheme (hwnd, NULL, NULL);
     return S_OK;
  }
 
@@ -60,7 +71,15 @@
  */
 BOOL WINAPI IsThemeDialogTextureEnabled(HWND hwnd)
 {
+    DWORD dwDialogTextureFlags;
     TRACE("(%p)\n", hwnd);
+
+    dwDialogTextureFlags = (DWORD)GetPropW (hwnd, 
+        MAKEINTATOMW (atDialogThemeEnabled));
+    if (dwDialogTextureFlags == 0) 
+        /* Means EnableThemeDialogTexture wasn't called for this dialog */
+        return TRUE;
+
     return (dwDialogTextureFlags & ETDT_ENABLE) && !(dwDialogTextureFlags & ETDT_DISABLE);
 }
 
@@ -95,7 +114,7 @@
         MapWindowPoints(hParent, NULL, (LPPOINT)&rt, 2);
     }
 
-    SetViewportOrgEx(hdc, rt.left, rt.top, &org);
+    OffsetViewportOrgEx(hdc, -rt.left, -rt.top, &org);
 
     SendMessageW(hParent, WM_ERASEBKGND, (WPARAM)hdc, 0);
     SendMessageW(hParent, WM_PRINTCLIENT, (WPARAM)hdc, PRF_CLIENT);
@@ -190,7 +209,7 @@
                           HBITMAP *hBmp, RECT *bmpRect)
 {
     int imagelayout = IL_VERTICAL;
-    int imagecount = 0;
+    int imagecount = 1;
     BITMAP bmp;
     WCHAR szPath[MAX_PATH];
     PTHEME_PROPERTY tp = UXTHEME_SelectImage(hTheme, hdc, iPartId, iStateId, pRect, glyph);
@@ -213,12 +232,12 @@
         int height = bmp.bmHeight/imagecount;
         bmpRect->left = 0;
         bmpRect->right = bmp.bmWidth;
-        bmpRect->top = (min(imagecount, iStateId)-1) * height;
+        bmpRect->top = (max(min(imagecount, iStateId), 1)-1) * height;
         bmpRect->bottom = bmpRect->top + height;
     }
     else {
         int width = bmp.bmWidth/imagecount;
-        bmpRect->left = (min(imagecount, iStateId)-1) * width;
+        bmpRect->left = (max(min(imagecount, iStateId), 1)-1) * width;
         bmpRect->right = bmpRect->left + width;
         bmpRect->top = 0;
         bmpRect->bottom = bmp.bmHeight;
@@ -302,8 +321,8 @@
     GetThemeBool(hTheme, iPartId, iStateId, TMT_GLYPHTRANSPARENT, &transparent);
     if(transparent) {
         if(FAILED(GetThemeColor(hTheme, iPartId, iStateId, TMT_GLYPHTRANSPARENTCOLOR, &transparentcolor))) {
-            /* If image is transparent, but no color was specified, get the color of the upper left corner */
-            transparentcolor = GetPixel(hdcSrc, 0, 0);
+            /* If image is transparent, but no color was specified, use magenta */
+            transparentcolor = RGB(255, 0, 255);
         }
     }
     GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_VALIGN, &valign);
@@ -588,15 +607,17 @@
 
     GetThemeInt(hTheme, iPartId, iStateId, TMT_BORDERSIZE, &bordersize);
     if(bordersize > 0) {
-        POINT ptCorners[4];
+        POINT ptCorners[5];
         ptCorners[0].x = pRect->left;
         ptCorners[0].y = pRect->top;
-        ptCorners[1].x = pRect->right;
+        ptCorners[1].x = pRect->right-1;
         ptCorners[1].y = pRect->top;
-        ptCorners[2].x = pRect->right;
-        ptCorners[2].y = pRect->bottom;
+        ptCorners[2].x = pRect->right-1;
+        ptCorners[2].y = pRect->bottom-1;
         ptCorners[3].x = pRect->left;
-        ptCorners[3].y = pRect->bottom;
+        ptCorners[3].y = pRect->bottom-1;
+        ptCorners[4].x = pRect->left;
+        ptCorners[4].y = pRect->top;
 
         InflateRect(pRect, -bordersize, -bordersize);
         if(pOptions->dwFlags & DTBG_OMITBORDER)
@@ -607,7 +628,7 @@
             return HRESULT_FROM_WIN32(GetLastError());
         oldPen = SelectObject(hdc, hPen);
 
-        if(!Polyline(hdc, ptCorners, 4))
+        if(!Polyline(hdc, ptCorners, 5))
             hr = HRESULT_FROM_WIN32(GetLastError());
 
         SelectObject(hdc, oldPen);
@@ -855,15 +876,34 @@
     if(!hTheme)
         return E_HANDLE;
 
+    /* try content margins property... */
     hr = GetThemeMargins(hTheme, hdc, iPartId, iStateId, TMT_CONTENTMARGINS, NULL, &margin);
-    if(FAILED(hr)) {
-        TRACE("Margins not found\n");
-        return hr;
+    if(SUCCEEDED(hr)) {
+        pContentRect->left = pBoundingRect->left + margin.cxLeftWidth;
+        pContentRect->top  = pBoundingRect->top + margin.cyTopHeight;
+        pContentRect->right = pBoundingRect->right - margin.cxRightWidth;
+        pContentRect->bottom = pBoundingRect->bottom - margin.cyBottomHeight;
+    } else {
+        /* otherwise, try to determine content rect from the background type and props */
+        int bgtype = BT_BORDERFILL;
+        memcpy(pContentRect, pBoundingRect, sizeof(RECT));
+
+        GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_BGTYPE, &bgtype);
+        if(bgtype == BT_BORDERFILL) {
+            int bordersize = 1;
+    
+            GetThemeInt(hTheme, iPartId, iStateId, TMT_BORDERSIZE, &bordersize);
+            InflateRect(pContentRect, -bordersize, -bordersize);
+        } else if ((bgtype == BT_IMAGEFILE)
+                && (SUCCEEDED(hr = GetThemeMargins(hTheme, hdc, iPartId, iStateId, 
+                TMT_SIZINGMARGINS, NULL, &margin)))) {
+            pContentRect->left = pBoundingRect->left + margin.cxLeftWidth;
+            pContentRect->top  = pBoundingRect->top + margin.cyTopHeight;
+            pContentRect->right = pBoundingRect->right - margin.cxRightWidth;
+            pContentRect->bottom = pBoundingRect->bottom - margin.cyBottomHeight;
+        }
+        /* If nothing was found, leave unchanged */
     }
-    pContentRect->left = pBoundingRect->left + margin.cxLeftWidth;
-    pContentRect->top  = pBoundingRect->top + margin.cyTopHeight;
-    pContentRect->right = pBoundingRect->right - margin.cxRightWidth;
-    pContentRect->bottom = pBoundingRect->bottom - margin.cyBottomHeight;
 
     TRACE("left:%ld,top:%ld,right:%ld,bottom:%ld\n", pContentRect->left, pContentRect->top, pContentRect->right, pContentRect->bottom);
 

Modified: trunk/reactos/lib/uxtheme/msstyles.c
--- trunk/reactos/lib/uxtheme/msstyles.c	2005-08-12 18:17:37 UTC (rev 17341)
+++ trunk/reactos/lib/uxtheme/msstyles.c	2005-08-12 18:22:47 UTC (rev 17342)
@@ -253,7 +253,7 @@
  *
  * Retrieve the ini file for the selected color/style
  */
-PUXINI_FILE MSSTYLES_GetActiveThemeIni(PTHEME_FILE tf)
+static PUXINI_FILE MSSTYLES_GetActiveThemeIni(PTHEME_FILE tf)
 {
     static const WCHAR szFileResNamesResource[] = {
         'F','I','L','E','R','E','S','N','A','M','E','S','\0'
@@ -320,7 +320,7 @@
  *     iPartId             Location to store part id
  *     iStateId            Location to store state id
  */
-BOOL MSSTYLES_ParseIniSectionName(LPCWSTR lpSection, DWORD dwLen, LPWSTR szAppName, LPWSTR szClassName, int *iPartId, int *iStateId)
+static BOOL MSSTYLES_ParseIniSectionName(LPCWSTR lpSection, DWORD dwLen, LPWSTR szAppName, LPWSTR szClassName, int *iPartId, int *iStateId)
 {
     WCHAR sec[255];
     WCHAR part[60] = {'\0'};
@@ -423,7 +423,7 @@
  * RETURNS
  *  The class added, or a class previously added with the same name
  */
-PTHEME_CLASS MSSTYLES_AddClass(PTHEME_FILE tf, LPCWSTR pszAppName, LPCWSTR pszClassName)
+static PTHEME_CLASS MSSTYLES_AddClass(PTHEME_FILE tf, LPCWSTR pszAppName, LPCWSTR pszClassName)
 {
     PTHEME_CLASS cur = MSSTYLES_FindClass(tf, pszAppName, pszClassName);
     if(cur) return cur;
@@ -480,7 +480,7 @@
  * RETURNS
  *  The part/state added, or a part/state previously added with the same IDs
  */
-PTHEME_PARTSTATE MSSTYLES_AddPartState(PTHEME_CLASS tc, int iPartId, int iStateId)
+static PTHEME_PARTSTATE MSSTYLES_AddPartState(PTHEME_CLASS tc, int iPartId, int iStateId)
 {
     PTHEME_PARTSTATE cur = MSSTYLES_FindPartState(tc, iPartId, iStateId, NULL);
     if(cur) return cur;
@@ -507,7 +507,7 @@
  * RETURNS
  *  The property found, or NULL
  */
-PTHEME_PROPERTY MSSTYLES_LFindProperty(PTHEME_PROPERTY tp, int iPropertyPrimitive, int iPropertyId)
+static PTHEME_PROPERTY MSSTYLES_LFindProperty(PTHEME_PROPERTY tp, int iPropertyPrimitive, int iPropertyId)
 {
     PTHEME_PROPERTY cur = tp;
     while(cur) {
@@ -596,7 +596,7 @@
  * RETURNS
  *  The property added, or a property previously added with the same IDs
  */
-PTHEME_PROPERTY MSSTYLES_AddProperty(PTHEME_PARTSTATE ps, int iPropertyPrimitive, int iPropertyId, LPCWSTR lpValue, DWORD dwValueLen, BOOL isGlobal)
+static PTHEME_PROPERTY MSSTYLES_AddProperty(PTHEME_PARTSTATE ps, int iPropertyPrimitive, int iPropertyId, LPCWSTR lpValue, DWORD dwValueLen, BOOL isGlobal)
 {
     PTHEME_PROPERTY cur = MSSTYLES_PSFindProperty(ps, iPropertyPrimitive, iPropertyId);
     /* Should duplicate properties overwrite the original, or be ignored? */
@@ -637,7 +637,7 @@
  * RETURNS
  *  The property added, or a property previously added with the same IDs
  */
-PTHEME_PROPERTY MSSTYLES_AddMetric(PTHEME_FILE tf, int iPropertyPrimitive, int iPropertyId, LPCWSTR lpValue, DWORD dwValueLen)
+static PTHEME_PROPERTY MSSTYLES_AddMetric(PTHEME_FILE tf, int iPropertyPrimitive, int iPropertyId, LPCWSTR lpValue, DWORD dwValueLen)
 {
     PTHEME_PROPERTY cur = MSSTYLES_FFindMetric(tf, iPropertyPrimitive, iPropertyId);
     /* Should duplicate properties overwrite the original, or be ignored? */
@@ -709,6 +709,10 @@
                             FIXME("Invalid color value for %s\n", debugstr_w(szPropertyName));
                         }
                     }
+		    else if (iPropertyId == TMT_FLATMENUS) {
+			BOOL flatMenus = (*lpValue == 'T') || (*lpValue == 't');
+			SystemParametersInfoW (SPI_SETFLATMENU, 0, (PVOID)flatMenus, 0);
+		    }
                     /* Catch all metrics, including colors */
                     MSSTYLES_AddMetric(tf, iPropertyPrimitive, iPropertyId, lpValue, dwValueLen);
                 }
@@ -806,6 +810,8 @@
     }
     if(cls) {
         TRACE("Opened app %s, class %s from list %s\n", debugstr_w(cls->szAppName), debugstr_w(cls->szClassName), debugstr_w(pszClassList));
+	cls->tf = tfActiveTheme;
+	cls->tf->dwRefCount++;
     }
     return cls;
 }
@@ -819,11 +825,12 @@
  *     tc                  Theme class to close
  *
  * NOTES
- *  There is currently no need clean anything up for theme classes,
- *  so do nothing for now
+ *  The MSSTYLES_CloseThemeFile decreases the refcount of the owning
+ *  theme file and cleans it up, if needed.
  */
 HRESULT MSSTYLES_CloseThemeClass(PTHEME_CLASS tc)
 {
+    MSSTYLES_CloseThemeFile (tc->tf);
     return S_OK;
 }
 

Modified: trunk/reactos/lib/uxtheme/msstyles.h
--- trunk/reactos/lib/uxtheme/msstyles.h	2005-08-12 18:17:37 UTC (rev 17341)
+++ trunk/reactos/lib/uxtheme/msstyles.h	2005-08-12 18:22:47 UTC (rev 17342)
@@ -46,8 +46,11 @@
     struct _THEME_PARTSTATE *next;
 } THEME_PARTSTATE, *PTHEME_PARTSTATE;
 
+struct _THEME_FILE;
+
 typedef struct _THEME_CLASS {
     HMODULE hTheme;
+    struct _THEME_FILE* tf;
     WCHAR szAppName[MAX_THEME_APP_NAME];
     WCHAR szClassName[MAX_THEME_CLASS_NAME];
     PTHEME_PARTSTATE partstate;

Modified: trunk/reactos/lib/uxtheme/system.c
--- trunk/reactos/lib/uxtheme/system.c	2005-08-12 18:17:37 UTC (rev 17341)
+++ trunk/reactos/lib/uxtheme/system.c	2005-08-12 18:22:47 UTC (rev 17342)
@@ -62,6 +62,7 @@
 ATOM atWindowTheme;
 ATOM atSubAppName;
 ATOM atSubIdList;
+ATOM atDialogThemeEnabled;
 
 BOOL bThemeActive = FALSE;
 WCHAR szCurrentTheme[MAX_PATH];
@@ -70,6 +71,27 @@
 
 /***********************************************************************/
 
+static BOOL CALLBACK UXTHEME_broadcast_msg_enumchild (HWND hWnd, LPARAM msg)
+{
+    PostMessageW(hWnd, msg, 0, 0);
+    return TRUE;
+}
+
+/* Broadcast a message to *all* windows, including children */
+static BOOL CALLBACK UXTHEME_broadcast_msg (HWND hWnd, LPARAM msg)
+{
+    if (hWnd == NULL)
+    {
+	EnumWindows (UXTHEME_broadcast_msg, msg);
+    }
+    else
+    {
+	PostMessageW(hWnd, msg, 0, 0);
+	EnumChildWindows (hWnd, UXTHEME_broadcast_msg_enumchild, msg);
+    }
+    return TRUE;
+}
+
 /***********************************************************************
  *      UXTHEME_LoadTheme
  *
@@ -78,7 +100,7 @@
 static void UXTHEME_LoadTheme(void)
 {
     HKEY hKey;
-    LONG buffsize;
+    DWORD buffsize;
     HRESULT hr;
     WCHAR tmp[10];
     PTHEME_FILE pt;
@@ -169,9 +191,12 @@
         tmp[1] = '\0';
         RegSetValueExW(hKey, szThemeActive, 0, REG_SZ, (const BYTE*)tmp, sizeof(WCHAR)*2);
         if(bThemeActive) {
-            RegSetValueExW(hKey, szColorName, 0, REG_SZ, (const BYTE*)szCurrentColor, lstrlenW(szCurrentColor)+1);
-            RegSetValueExW(hKey, szSizeName, 0, REG_SZ, (const BYTE*)szCurrentSize, lstrlenW(szCurrentSize)+1);
-            RegSetValueExW(hKey, szDllName, 0, REG_SZ, (const BYTE*)szCurrentTheme, lstrlenW(szCurrentTheme)+1);
+            RegSetValueExW(hKey, szColorName, 0, REG_SZ, (const BYTE*)szCurrentColor, 
+		(lstrlenW(szCurrentColor)+1)*sizeof(WCHAR));
+            RegSetValueExW(hKey, szSizeName, 0, REG_SZ, (const BYTE*)szCurrentSize, 
+		(lstrlenW(szCurrentSize)+1)*sizeof(WCHAR));
+            RegSetValueExW(hKey, szDllName, 0, REG_SZ, (const BYTE*)szCurrentTheme, 
+		(lstrlenW(szCurrentTheme)+1)*sizeof(WCHAR));
         }
         else {
             RegDeleteValueW(hKey, szColorName);
@@ -200,12 +225,16 @@
     static const WCHAR szSubIdList[] = {
         'u','x','_','s','u','b','i','d','l','s','t','\0'
     };
+    static const WCHAR szDialogThemeEnabled[] = {
+        'u','x','_','d','i','a','l','o','g','t','h','e','m','e','\0'
+    };
 
     hDllInst = hInst;
 
-    atWindowTheme = GlobalAddAtomW(szWindowTheme);
-    atSubAppName  = GlobalAddAtomW(szSubAppName);
-    atSubIdList   = GlobalAddAtomW(szSubIdList);
+    atWindowTheme        = GlobalAddAtomW(szWindowTheme);
+    atSubAppName         = GlobalAddAtomW(szSubAppName);
+    atSubIdList          = GlobalAddAtomW(szSubIdList);
+    atDialogThemeEnabled = GlobalAddAtomW(szDialogThemeEnabled);
 
     UXTHEME_LoadTheme();
 }
@@ -247,7 +276,7 @@
             RegSetValueExW(hKey, szThemeActive, 0, REG_SZ, (LPBYTE)szEnabled, sizeof(WCHAR));
             RegCloseKey(hKey);
         }
-        PostMessageW(HWND_BROADCAST, WM_THEMECHANGED, 0, 0);
+	UXTHEME_broadcast_msg (NULL, WM_THEMECHANGED);
     }
     return S_OK;
 }
@@ -295,20 +324,23 @@
     WCHAR szClassBuff[256];
     LPCWSTR pszAppName;
     LPCWSTR pszUseClassList;
-    HTHEME hTheme;
-    TRACE("(%p,%s)\n", hwnd, debugstr_w(pszClassList));
-    if(!bThemeActive)
-        return NULL;
+    HTHEME hTheme = NULL;
+    TRACE("(%p,%s)", hwnd, debugstr_w(pszClassList));
 
-    pszAppName = UXTHEME_GetWindowProperty(hwnd, atSubAppName, szAppBuff, sizeof(szAppBuff)/sizeof(szAppBuff[0]));
-    /* If SetWindowTheme was used on the window, that overrides the class list passed to this function */
-    pszUseClassList = UXTHEME_GetWindowProperty(hwnd, atSubIdList, szClassBuff, sizeof(szClassBuff)/sizeof(szClassBuff[0]));
-    if(!pszUseClassList)
-        pszUseClassList = pszClassList;
+    if(bThemeActive)
+    {
+        pszAppName = UXTHEME_GetWindowProperty(hwnd, atSubAppName, szAppBuff, sizeof(szAppBuff)/sizeof(szAppBuff[0]));
+        /* If SetWindowTheme was used on the window, that overrides the class list passed to this function */
+        pszUseClassList = UXTHEME_GetWindowProperty(hwnd, atSubIdList, szClassBuff, sizeof(szClassBuff)/sizeof(szClassBuff[0]));
+        if(!pszUseClassList)
+            pszUseClassList = pszClassList;
 
-    hTheme = MSSTYLES_OpenThemeClass(pszAppName, pszUseClassList);
+        if (pszUseClassList)
+            hTheme = MSSTYLES_OpenThemeClass(pszAppName, pszUseClassList);
+    }
     if(IsWindow(hwnd))
         SetPropW(hwnd, MAKEINTATOMW(atWindowTheme), hTheme);
+    TRACE(" = %p\n", hTheme);
     return hTheme;
 }
 
@@ -338,7 +370,7 @@
     if(SUCCEEDED(hr))
         hr = UXTHEME_SetWindowProperty(hwnd, atSubIdList, pszSubIdList);
     if(SUCCEEDED(hr))
-        PostMessageW(hwnd, WM_THEMECHANGED, 0, 0);
+	UXTHEME_broadcast_msg (hwnd, WM_THEMECHANGED);
     return hr;
 }
 
@@ -554,7 +586,7 @@
     HRESULT hr;
     TRACE("(%p,%s,%p)\n", hThemeFile, unknown, hWnd);
     hr = UXTHEME_SetActiveTheme(hThemeFile);
-    PostMessageW(HWND_BROADCAST, WM_THEMECHANGED, 0, 0);
+    UXTHEME_broadcast_msg (NULL, WM_THEMECHANGED);
     return hr;
 }