Sync to Wine-20050830:
authorGé van Geldorp <ge@gse.nl>
Wed, 7 Sep 2005 16:22:51 +0000 (16:22 +0000)
committerGé van Geldorp <ge@gse.nl>
Wed, 7 Sep 2005 16:22:51 +0000 (16:22 +0000)
Kevin Koltzau <kevin@plop.org>
- Fix 'cast to pointer from integer of different size' warnings in
  64bit.
Frank Richter <frank.richter@gmail.com>
- Add support for the BT_NONE background type.
- Better computations to have uniformly sized parts scaled in both
  directions.
- Implement GetThemeBackgroundExtent().
- Implement DrawThemeEdge().
- Implement support for the ST_TILE background stretching mode.
- Implementation for GetThemePartSize() (not entirely equivalent to
  native uxtheme, but sensibly useable).
- 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.
- Make GetThemeMargins() return default values (0 margin) if the
  function does not succeed.
- More elaborate IsThemeBackgroundPartiallyTransparent() implementation;
  also returns TRUE for theme parts with 32bpp images.
- Since theme images are reused now it's not really a good idea to
  delete them in drawing functions.
- Pass around what kind of transparency an image actually needs. Use
  alpha-blending for 32bpp images.
- Set some default values for truesize sizing that seem closer to
  Windows.
- If a MINSIZEn property is not present, fall back to actual size of nth
  image to determine whether it is suitable.
- EnumThemeColors() and EnumThemeSizes() actually do not return a single
  string with the color/size name, but rather a struct containing three
  strings - name, display name and tooltip.
- The default image layout is HORIZONTAL, not VERTICAL.
- Take a common computation out of two if-branches in
  UXTHEME_LoadImage().
- Compare result of RegQueryValueExW() with ERROR_SUCCESS.
- Another fix to use magenta as the default transparent color.
- Implement "manual" image sharing(as opposed to using LoadImage() with
  LR_SHARED) by keeping the loaded images in a list. This is needed for
  proper alpha support later on since once-per-image preparations will
  be needed then.
- Add support for horizontal & vertical alignment when doing truesize
  sizing.
- Whatever TrueSizeStretchMark is for - it's not what Wine uxtheme used
  it for. Native uxtheme always stretches "truesize" parts when the
  destination is smaller than the part image size, but
  TrueSizeStretchMark doesn't seem to have an influence.

svn path=/trunk/; revision=17719

reactos/lib/uxtheme/Makefile.in [deleted file]
reactos/lib/uxtheme/draw.c
reactos/lib/uxtheme/msstyles.c
reactos/lib/uxtheme/msstyles.h
reactos/lib/uxtheme/property.c
reactos/lib/uxtheme/system.c
reactos/lib/uxtheme/uxtheme.spec
reactos/lib/uxtheme/uxthemedll.h

diff --git a/reactos/lib/uxtheme/Makefile.in b/reactos/lib/uxtheme/Makefile.in
deleted file mode 100644 (file)
index 27e46a5..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-TOPSRCDIR = @top_srcdir@
-TOPOBJDIR = ../..
-SRCDIR    = @srcdir@
-VPATH     = @srcdir@
-MODULE    = uxtheme.dll
-IMPORTLIB = libuxtheme.$(IMPLIBEXT)
-IMPORTS   = shlwapi user32 gdi32 advapi32 kernel32 ntdll
-DELAYIMPORTS = msimg32
-EXTRALIBS = $(LIBUNICODE)
-
-C_SRCS = \
-       draw.c \
-       main.c \
-       metric.c \
-       msstyles.c \
-       property.c \
-       stylemap.c \
-       system.c \
-       uxini.c
-
-RC_SRCS = version.rc
-
-@MAKE_DLL_RULES@
-
-### Dependencies:
index 69e30c0..1a80f6d 100644 (file)
@@ -187,12 +187,42 @@ static PTHEME_PROPERTY UXTHEME_SelectImage(HTHEME hTheme, HDC hdc, int iPartId,
         POINT size = {pRect->right-pRect->left, pRect->bottom-pRect->top};
         POINT reqsize;
         for(i=4; i>=0; i--) {
-            if(SUCCEEDED(GetThemePosition(hTheme, iPartId, iStateId, i + TMT_MINSIZE1, &reqsize))) {
-                if(reqsize.x >= size.x && reqsize.y >= size.y) {
-                    TRACE("Using image size %ldx%ld, image %d\n", reqsize.x, reqsize.y, i + TMT_IMAGEFILE1);
-                    return MSSTYLES_FindProperty(hTheme, iPartId, iStateId, TMT_FILENAME, i + TMT_IMAGEFILE1);
+            PTHEME_PROPERTY fileProp = 
+                MSSTYLES_FindProperty(hTheme, iPartId, iStateId, TMT_FILENAME, i + TMT_IMAGEFILE1);
+            if (!fileProp) continue;
+            if(FAILED(GetThemePosition(hTheme, iPartId, iStateId, i + TMT_MINSIZE1, &reqsize))) {
+                /* fall back to size of Nth image */
+                WCHAR szPath[MAX_PATH];
+                int imagelayout = IL_HORIZONTAL;
+                int imagecount = 1;
+                int imagenum;
+                BITMAP bmp;
+                HBITMAP hBmp;
+                BOOL hasAlpha;
+
+                lstrcpynW(szPath, fileProp->lpValue, 
+                    min(fileProp->dwValueLen+1, sizeof(szPath)/sizeof(szPath[0])));
+                hBmp = MSSTYLES_LoadBitmap(hTheme, szPath, &hasAlpha);
+                if(!hBmp) continue;
+
+                GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_IMAGELAYOUT, &imagelayout);
+                GetThemeInt(hTheme, iPartId, iStateId, TMT_IMAGECOUNT, &imagecount);
+
+                imagenum = max (min (imagecount, iStateId), 1) - 1;
+                GetObjectW(hBmp, sizeof(bmp), &bmp);
+                if(imagelayout == IL_VERTICAL) {
+                    reqsize.x = bmp.bmWidth;
+                    reqsize.y = bmp.bmHeight/imagecount;
+                }
+                else {
+                    reqsize.x = bmp.bmWidth/imagecount;
+                    reqsize.y = bmp.bmHeight;
                 }
             }
+            if(reqsize.x <= size.x && reqsize.y <= size.y) {
+                TRACE("Using image size %ldx%ld, image %d\n", reqsize.x, reqsize.y, i + TMT_IMAGEFILE1);
+                return fileProp;
+            }
         }
         /* If an image couldnt be selected, choose the smallest one */
         return MSSTYLES_FindProperty(hTheme, iPartId, iStateId, TMT_FILENAME, TMT_IMAGEFILE1);
@@ -206,10 +236,11 @@ static PTHEME_PROPERTY UXTHEME_SelectImage(HTHEME hTheme, HDC hdc, int iPartId,
  * Load image for part/state
  */
 static HRESULT UXTHEME_LoadImage(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, BOOL glyph,
-                          HBITMAP *hBmp, RECT *bmpRect)
+                          HBITMAP *hBmp, RECT *bmpRect, BOOL* hasImageAlpha)
 {
-    int imagelayout = IL_VERTICAL;
+    int imagelayout = IL_HORIZONTAL;
     int imagecount = 1;
+    int imagenum;
     BITMAP bmp;
     WCHAR szPath[MAX_PATH];
     PTHEME_PROPERTY tp = UXTHEME_SelectImage(hTheme, hdc, iPartId, iStateId, pRect, glyph);
@@ -218,7 +249,7 @@ static HRESULT UXTHEME_LoadImage(HTHEME hTheme, HDC hdc, int iPartId, int iState
         return E_PROP_ID_UNSUPPORTED;
     }
     lstrcpynW(szPath, tp->lpValue, min(tp->dwValueLen+1, sizeof(szPath)/sizeof(szPath[0])));
-    *hBmp = MSSTYLES_LoadBitmap(hdc, hTheme, szPath);
+    *hBmp = MSSTYLES_LoadBitmap(hTheme, szPath, hasImageAlpha);
     if(!*hBmp) {
         TRACE("Failed to load bitmap %s\n", debugstr_w(szPath));
         return HRESULT_FROM_WIN32(GetLastError());
@@ -227,17 +258,18 @@ static HRESULT UXTHEME_LoadImage(HTHEME hTheme, HDC hdc, int iPartId, int iState
     GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_IMAGELAYOUT, &imagelayout);
     GetThemeInt(hTheme, iPartId, iStateId, TMT_IMAGECOUNT, &imagecount);
 
+    imagenum = max (min (imagecount, iStateId), 1) - 1;
     GetObjectW(*hBmp, sizeof(bmp), &bmp);
     if(imagelayout == IL_VERTICAL) {
         int height = bmp.bmHeight/imagecount;
         bmpRect->left = 0;
         bmpRect->right = bmp.bmWidth;
-        bmpRect->top = (max(min(imagecount, iStateId), 1)-1) * height;
+        bmpRect->top = imagenum * height;
         bmpRect->bottom = bmpRect->top + height;
     }
     else {
         int width = bmp.bmWidth/imagecount;
-        bmpRect->left = (max(min(imagecount, iStateId), 1)-1) * width;
+        bmpRect->left = imagenum * width;
         bmpRect->right = bmpRect->left + width;
         bmpRect->top = 0;
         bmpRect->bottom = bmp.bmHeight;
@@ -248,22 +280,35 @@ static HRESULT UXTHEME_LoadImage(HTHEME hTheme, HDC hdc, int iPartId, int iState
 /***********************************************************************
  *      UXTHEME_StretchBlt
  *
- * Psudo TransparentBlt/StretchBlt
+ * Pseudo TransparentBlt/StretchBlt
  */
 static inline BOOL UXTHEME_StretchBlt(HDC hdcDst, int nXOriginDst, int nYOriginDst, int nWidthDst, int nHeightDst,
                                       HDC hdcSrc, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc,
-                                      BOOL transparent, COLORREF transcolor)
+                                      INT transparent, COLORREF transcolor)
 {
-    if(transparent) {
+    static const BLENDFUNCTION blendFunc = 
+    {
+      AC_SRC_OVER, /* BlendOp */
+      0,           /* BlendFlag */
+      255,         /* SourceConstantAlpha */
+      AC_SRC_ALPHA /* AlphaFormat */
+    };
+    if (transparent == ALPHABLEND_BINARY) {
         /* Ensure we don't pass any negative values to TransparentBlt */
         return TransparentBlt(hdcDst, nXOriginDst, nYOriginDst, abs(nWidthDst), abs(nHeightDst),
                               hdcSrc, nXOriginSrc, nYOriginSrc, abs(nWidthSrc), abs(nHeightSrc),
                               transcolor);
     }
-    /* This should be using AlphaBlend */
-    return StretchBlt(hdcDst, nXOriginDst, nYOriginDst, nWidthDst, nHeightDst,
-                        hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc,
-                        SRCCOPY);
+    if ((transparent == ALPHABLEND_NONE) ||
+        !AlphaBlend(hdcDst, nXOriginDst, nYOriginDst, nWidthDst, nHeightDst,
+                    hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc,
+                    blendFunc))
+    {
+        return StretchBlt(hdcDst, nXOriginDst, nYOriginDst, nWidthDst, nHeightDst,
+                          hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc,
+                          SRCCOPY);
+    }
+    return TRUE;
 }
 
 /***********************************************************************
@@ -273,13 +318,87 @@ static inline BOOL UXTHEME_StretchBlt(HDC hdcDst, int nXOriginDst, int nYOriginD
  */
 static inline BOOL UXTHEME_Blt(HDC hdcDest, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest,
                                HDC hdcSrc, int nXOriginSrc, int nYOriginSrc,
-                               BOOL transparent, COLORREF transcolor)
+                               INT transparent, COLORREF transcolor)
 {
     return UXTHEME_StretchBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest,
                               hdcSrc, nXOriginSrc, nYOriginSrc, nWidthDest, nHeightDest,
                               transparent, transcolor);
 }
 
+/***********************************************************************
+ *      UXTHEME_SizedBlt
+ *
+ * Stretches or tiles, depending on sizingtype.
+ */
+static inline BOOL UXTHEME_SizedBlt (HDC hdcDst, int nXOriginDst, int nYOriginDst, 
+                                     int nWidthDst, int nHeightDst,
+                                     HDC hdcSrc, int nXOriginSrc, int nYOriginSrc, 
+                                     int nWidthSrc, int nHeightSrc,
+                                     int sizingtype, 
+                                     INT transparent, COLORREF transcolor)
+{
+    if (sizingtype == ST_TILE)
+    {
+        int yOfs = nYOriginDst;
+        int yRemaining = nHeightDst;
+        while (yRemaining > 0)
+        {
+            int bltHeight = min (yRemaining, nHeightSrc);
+            int xOfs = nXOriginDst;
+            int xRemaining = nWidthDst;
+            while (xRemaining > 0)
+            {
+                int bltWidth = min (xRemaining, nWidthSrc);
+                if (!UXTHEME_Blt (hdcDst, xOfs, yOfs, bltWidth, bltHeight,
+                                  hdcSrc, nXOriginSrc, nYOriginSrc, 
+                                  transparent, transcolor))
+                    return FALSE;
+                xOfs += nWidthSrc;
+                xRemaining -= nWidthSrc;
+            }
+            yOfs += nHeightSrc;
+            yRemaining -= nHeightSrc;
+        }
+        return TRUE;
+    }
+    else
+    {
+        return UXTHEME_StretchBlt (hdcDst, nXOriginDst, nYOriginDst, nWidthDst, nHeightDst,
+                                   hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc,
+                                   transparent, transcolor);
+    }
+}
+
+/* Get transparency parameters passed to UXTHEME_StretchBlt() - the parameters 
+ * depend on whether the image has full alpha  or whether it is 
+ * color-transparent or just opaque. */
+static inline void get_transparency (HTHEME hTheme, int iPartId, int iStateId, 
+                                     BOOL hasImageAlpha, INT* transparent,
+                                     COLORREF* transparentcolor, BOOL glyph)
+{
+    if (hasImageAlpha)
+    {
+        *transparent = ALPHABLEND_FULL;
+        *transparentcolor = RGB (255, 0, 255);
+    }
+    else
+    {
+        BOOL trans = FALSE;
+        GetThemeBool(hTheme, iPartId, iStateId, 
+            glyph ? TMT_GLYPHTRANSPARENT : TMT_TRANSPARENT, &trans);
+        if(trans) {
+            *transparent = ALPHABLEND_BINARY;
+            if(FAILED(GetThemeColor(hTheme, iPartId, iStateId, 
+                glyph ? TMT_GLYPHTRANSPARENTCOLOR : TMT_TRANSPARENTCOLOR, 
+                transparentcolor))) {
+                /* If image is transparent, but no color was specified, use magenta */
+                *transparentcolor = RGB(255, 0, 255);
+            }
+        }
+        else
+            *transparent = ALPHABLEND_NONE;
+    }
+}
 
 /***********************************************************************
  *      UXTHEME_DrawImageGlyph
@@ -295,20 +414,21 @@ static HRESULT UXTHEME_DrawImageGlyph(HTHEME hTheme, HDC hdc, int iPartId,
     HDC hdcSrc = NULL;
     HGDIOBJ oldSrc = NULL;
     RECT rcSrc;
-    BOOL transparent = FALSE;
-    COLORREF transparentcolor = 0;
+    INT transparent = FALSE;
+    COLORREF transparentcolor;
     int valign = VA_CENTER;
     int halign = HA_CENTER;
     POINT dstSize;
     POINT srcSize;
     POINT topleft;
+    BOOL hasAlpha;
 
-    hr = UXTHEME_LoadImage(hTheme, hdc, iPartId, iStateId, pRect, TRUE, &bmpSrc, &rcSrc);
+    hr = UXTHEME_LoadImage(hTheme, hdc, iPartId, iStateId, pRect, TRUE, 
+        &bmpSrc, &rcSrc, &hasAlpha);
     if(FAILED(hr)) return hr;
     hdcSrc = CreateCompatibleDC(hdc);
     if(!hdcSrc) {
         hr = HRESULT_FROM_WIN32(GetLastError());
-        DeleteObject(bmpSrc);
         return hr;
     }
     oldSrc = SelectObject(hdcSrc, bmpSrc);
@@ -318,13 +438,8 @@ static HRESULT UXTHEME_DrawImageGlyph(HTHEME hTheme, HDC hdc, int iPartId,
     srcSize.x = rcSrc.right-rcSrc.left;
     srcSize.y = rcSrc.bottom-rcSrc.top;
 
-    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, use magenta */
-            transparentcolor = RGB(255, 0, 255);
-        }
-    }
+    get_transparency (hTheme, iPartId, iStateId, hasAlpha, &transparent,
+        &transparentcolor, TRUE);
     GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_VALIGN, &valign);
     GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_HALIGN, &halign);
 
@@ -343,7 +458,6 @@ static HRESULT UXTHEME_DrawImageGlyph(HTHEME hTheme, HDC hdc, int iPartId,
 
     SelectObject(hdcSrc, oldSrc);
     DeleteDC(hdcSrc);
-    DeleteObject(bmpSrc);
     return hr;
 }
 
@@ -370,6 +484,110 @@ static HRESULT UXTHEME_DrawGlyph(HTHEME hTheme, HDC hdc, int iPartId,
     return S_OK;
 }
 
+/***********************************************************************
+ * get_image_part_size
+ *
+ * Used by GetThemePartSize and UXTHEME_DrawImageBackground
+ */
+static HRESULT get_image_part_size (HTHEME hTheme, HDC hdc, int iPartId,
+                                    int iStateId, RECT *prc, THEMESIZE eSize,
+                                    POINT *psz)
+{
+    HRESULT hr = S_OK;
+    HBITMAP bmpSrc;
+    RECT rcSrc;
+    BOOL hasAlpha;
+
+    hr = UXTHEME_LoadImage(hTheme, hdc, iPartId, iStateId, prc, FALSE, 
+        &bmpSrc, &rcSrc, &hasAlpha);
+    if (FAILED(hr)) return hr;
+
+    switch (eSize)
+    {
+        case TS_DRAW:
+            if (prc != NULL)
+            {
+                RECT rcDst;
+                POINT dstSize;
+                POINT srcSize;
+                int sizingtype = ST_STRETCH;
+                BOOL uniformsizing = FALSE;
+
+                CopyRect(&rcDst, prc);
+
+                dstSize.x = rcDst.right-rcDst.left;
+                dstSize.y = rcDst.bottom-rcDst.top;
+                srcSize.x = rcSrc.right-rcSrc.left;
+                srcSize.y = rcSrc.bottom-rcSrc.top;
+            
+                GetThemeBool(hTheme, iPartId, iStateId, TMT_UNIFORMSIZING, &uniformsizing);
+                if(uniformsizing) {
+                    /* Scale height and width equally */
+                    if (dstSize.x*srcSize.y < dstSize.y*srcSize.x)
+                    {
+                        dstSize.y = MulDiv (srcSize.y, dstSize.x, srcSize.x);
+                        rcDst.bottom = rcDst.top + dstSize.y;
+                    }
+                    else
+                    {
+                        dstSize.x = MulDiv (srcSize.x, dstSize.y, srcSize.y);
+                        rcDst.right = rcDst.left + dstSize.x;
+                    }
+                }
+            
+                GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_SIZINGTYPE, &sizingtype);
+                if(sizingtype == ST_TRUESIZE) {
+                    int truesizestretchmark = 100;
+            
+                    if(dstSize.x < 0 || dstSize.y < 0) {
+                        BOOL mirrorimage = TRUE;
+                        GetThemeBool(hTheme, iPartId, iStateId, TMT_MIRRORIMAGE, &mirrorimage);
+                        if(mirrorimage) {
+                            if(dstSize.x < 0) {
+                                rcDst.left += dstSize.x;
+                                rcDst.right += dstSize.x;
+                            }
+                            if(dstSize.y < 0) {
+                                rcDst.top += dstSize.y;
+                                rcDst.bottom += dstSize.y;
+                            }
+                        }
+                    }
+                    /* Whatever TrueSizeStretchMark does - it does not seem to
+                     * be what's outlined below. It appears as if native 
+                     * uxtheme always stretches if dest is smaller than source
+                     * (ie as if TrueSizeStretchMark==100 with the code below) */
+#if 0
+                    /* Only stretch when target exceeds source by truesizestretchmark percent */
+                    GetThemeInt(hTheme, iPartId, iStateId, TMT_TRUESIZESTRETCHMARK, &truesizestretchmark);
+#endif
+                    if(dstSize.x < 0 || dstSize.y < 0 ||
+                      (MulDiv(srcSize.x, 100, dstSize.x) > truesizestretchmark &&
+                      MulDiv(srcSize.y, 100, dstSize.y) > truesizestretchmark)) {
+                        memcpy (psz, &dstSize, sizeof (SIZE));
+                    }
+                    else {
+                        memcpy (psz, &srcSize, sizeof (SIZE));
+                    }
+                }
+                else
+                {
+                    psz->x = abs(dstSize.x);
+                    psz->y = abs(dstSize.y);
+                }
+                break;
+            }
+            /* else fall through */
+        case TS_MIN:
+            /* FIXME: couldn't figure how native uxtheme computes min size */
+        case TS_TRUE:
+            psz->x = rcSrc.right - rcSrc.left;
+            psz->y = rcSrc.bottom - rcSrc.top;
+            break;
+    }
+    return hr;
+}
+
 /***********************************************************************
  *      UXTHEME_DrawImageBackground
  *
@@ -387,143 +605,101 @@ static HRESULT UXTHEME_DrawImageBackground(HTHEME hTheme, HDC hdc, int iPartId,
     RECT rcDst;
     POINT dstSize;
     POINT srcSize;
-    int sizingtype = ST_TRUESIZE;
-    BOOL uniformsizing = FALSE;
-    BOOL transparent = FALSE;
+    POINT drawSize;
+    int sizingtype = ST_STRETCH;
+    INT transparent;
     COLORREF transparentcolor = 0;
+    BOOL hasAlpha;
 
-    hr = UXTHEME_LoadImage(hTheme, hdc, iPartId, iStateId, pRect, FALSE, &bmpSrc, &rcSrc);
+    hr = UXTHEME_LoadImage(hTheme, hdc, iPartId, iStateId, pRect, FALSE, 
+        &bmpSrc, &rcSrc, &hasAlpha);
     if(FAILED(hr)) return hr;
     hdcSrc = CreateCompatibleDC(hdc);
     if(!hdcSrc) {
         hr = HRESULT_FROM_WIN32(GetLastError());
-        DeleteObject(bmpSrc);
         return hr;
     }
     oldSrc = SelectObject(hdcSrc, bmpSrc);
 
     CopyRect(&rcDst, pRect);
     
-    GetThemeBool(hTheme, iPartId, iStateId, TMT_TRANSPARENT, &transparent);
-    if(transparent) {
-        if(FAILED(GetThemeColor(hTheme, iPartId, iStateId, TMT_TRANSPARENTCOLOR, &transparentcolor))) {
-            /* If image is transparent, but no color was specified, get the color of the upper left corner */
-            transparentcolor = GetPixel(hdcSrc, 0, 0);
-        }
-    }
+    get_transparency (hTheme, iPartId, iStateId, hasAlpha, &transparent,
+        &transparentcolor, FALSE);
 
     dstSize.x = rcDst.right-rcDst.left;
     dstSize.y = rcDst.bottom-rcDst.top;
     srcSize.x = rcSrc.right-rcSrc.left;
     srcSize.y = rcSrc.bottom-rcSrc.top;
 
-    GetThemeBool(hTheme, iPartId, iStateId, TMT_UNIFORMSIZING, &uniformsizing);
-    if(uniformsizing) {
-        /* Scale height and width equally */
-        int widthDiff = abs(srcSize.x-dstSize.x);
-        int heightDiff = abs(srcSize.y-dstSize.x);
-        if(widthDiff > heightDiff) {
-            dstSize.y -= widthDiff-heightDiff;
-            rcDst.bottom = rcDst.top + dstSize.y;
-        }
-        else if(heightDiff > widthDiff) {
-            dstSize.x -= heightDiff-widthDiff;
-            rcDst.right = rcDst.left + dstSize.x;
-        }
-    }
-
     GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_SIZINGTYPE, &sizingtype);
     if(sizingtype == ST_TRUESIZE) {
-        int truesizestretchmark = 0;
-
-        if(dstSize.x < 0 || dstSize.y < 0) {
-            BOOL mirrorimage = TRUE;
-            GetThemeBool(hTheme, iPartId, iStateId, TMT_MIRRORIMAGE, &mirrorimage);
-            if(mirrorimage) {
-                if(dstSize.x < 0) {
-                    rcDst.left += dstSize.x;
-                    rcDst.right += dstSize.x;
-                }
-                if(dstSize.y < 0) {
-                    rcDst.top += dstSize.y;
-                    rcDst.bottom += dstSize.y;
-                }
-            }
-        }
-        /* Only stretch when target exceeds source by truesizestretchmark percent */
-        GetThemeInt(hTheme, iPartId, iStateId, TMT_TRUESIZESTRETCHMARK, &truesizestretchmark);
-        if(dstSize.x < 0 || dstSize.y < 0 ||
-           MulDiv(srcSize.x, 100, dstSize.x) > truesizestretchmark ||
-           MulDiv(srcSize.y, 100, dstSize.y) > truesizestretchmark) {
-            if(!UXTHEME_StretchBlt(hdc, rcDst.left, rcDst.top, dstSize.x, dstSize.y,
-                                   hdcSrc, rcSrc.left, rcSrc.top, srcSize.x, srcSize.y,
-                                   transparent, transparentcolor))
-                hr = HRESULT_FROM_WIN32(GetLastError());
-        }
-        else {
-            rcDst.left += (dstSize.x/2)-(srcSize.x/2);
-            rcDst.top  += (dstSize.y/2)-(srcSize.y/2);
-            rcDst.right = rcDst.left + srcSize.x;
-            rcDst.bottom = rcDst.top + srcSize.y;
-            if(!UXTHEME_Blt(hdc, rcDst.left, rcDst.top, srcSize.x, srcSize.y,
-                            hdcSrc, rcSrc.left, rcSrc.top,
-                            transparent, transparentcolor))
-                hr = HRESULT_FROM_WIN32(GetLastError());
-        }
+        int valign = VA_CENTER, halign = HA_CENTER;
+
+        get_image_part_size (hTheme, hdc, iPartId, iStateId, pRect, TS_DRAW, &drawSize);
+        GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_VALIGN, &valign);
+        GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_HALIGN, &halign);
+
+        if (halign == HA_CENTER)
+            rcDst.left += (dstSize.x/2)-(drawSize.x/2);
+        else if (halign == HA_RIGHT)
+            rcDst.left = rcDst.right - drawSize.x;
+        if (valign == VA_CENTER)
+            rcDst.top  += (dstSize.y/2)-(drawSize.y/2);
+        else if (valign == VA_BOTTOM)
+            rcDst.top = rcDst.bottom - drawSize.y;
+        rcDst.right = rcDst.left + drawSize.x;
+        rcDst.bottom = rcDst.top + drawSize.y;
+        if(!UXTHEME_StretchBlt(hdc, rcDst.left, rcDst.top, drawSize.x, drawSize.y,
+                                hdcSrc, rcSrc.left, rcSrc.top, srcSize.x, srcSize.y,
+                                transparent, transparentcolor))
+            hr = HRESULT_FROM_WIN32(GetLastError());
     }
     else {
         HDC hdcDst = NULL;
-        HBITMAP bmpDst = NULL;
-        HGDIOBJ oldDst = NULL;
         MARGINS sm;
+        POINT org;
 
         dstSize.x = abs(dstSize.x);
         dstSize.y = abs(dstSize.y);
 
         GetThemeMargins(hTheme, hdc, iPartId, iStateId, TMT_SIZINGMARGINS, NULL, &sm);
 
-        hdcDst = CreateCompatibleDC(hdc);
-        if(!hdcDst) {
-            hr = HRESULT_FROM_WIN32(GetLastError());
-            goto draw_error; 
-        }
-        bmpDst = CreateCompatibleBitmap(hdc, dstSize.x, dstSize.y);
-        if(!bmpDst) {
-            hr = HRESULT_FROM_WIN32(GetLastError());
-            goto draw_error; 
-        }
-        oldDst = SelectObject(hdcDst, bmpDst);
+        hdcDst = hdc;
+        OffsetViewportOrgEx(hdcDst, rcDst.left, rcDst.top, &org);
 
         /* Upper left corner */
-        if(!BitBlt(hdcDst, 0, 0, sm.cxLeftWidth, sm.cyTopHeight,
-                   hdcSrc, rcSrc.left, rcSrc.top, SRCCOPY)) {
+        if(!UXTHEME_Blt(hdcDst, 0, 0, sm.cxLeftWidth, sm.cyTopHeight,
+                        hdcSrc, rcSrc.left, rcSrc.top, 
+                        transparent, transparentcolor)) {
             hr = HRESULT_FROM_WIN32(GetLastError());
             goto draw_error; 
         }
         /* Upper right corner */
-        if(!BitBlt(hdcDst, dstSize.x-sm.cxRightWidth, 0, sm.cxRightWidth, sm.cyTopHeight,
-                   hdcSrc, rcSrc.right-sm.cxRightWidth, rcSrc.top, SRCCOPY)) {
+        if(!UXTHEME_Blt (hdcDst, dstSize.x-sm.cxRightWidth, 0, 
+                         sm.cxRightWidth, sm.cyTopHeight,
+                         hdcSrc, rcSrc.right-sm.cxRightWidth, rcSrc.top, 
+                         transparent, transparentcolor)) {
             hr = HRESULT_FROM_WIN32(GetLastError());
             goto draw_error; 
         }
         /* Lower left corner */
-        if(!BitBlt(hdcDst, 0, dstSize.y-sm.cyBottomHeight, sm.cxLeftWidth, sm.cyBottomHeight,
-                   hdcSrc, rcSrc.left, rcSrc.bottom-sm.cyBottomHeight, SRCCOPY)) {
+        if(!UXTHEME_Blt (hdcDst, 0, dstSize.y-sm.cyBottomHeight, 
+                         sm.cxLeftWidth, sm.cyBottomHeight,
+                         hdcSrc, rcSrc.left, rcSrc.bottom-sm.cyBottomHeight, 
+                         transparent, transparentcolor)) {
             hr = HRESULT_FROM_WIN32(GetLastError());
             goto draw_error; 
         }
         /* Lower right corner */
-        if(!BitBlt(hdcDst, dstSize.x-sm.cxRightWidth, dstSize.y-sm.cyBottomHeight, sm.cxRightWidth, sm.cyBottomHeight,
-                   hdcSrc, rcSrc.right-sm.cxRightWidth, rcSrc.bottom-sm.cyBottomHeight, SRCCOPY)) {
+        if(!UXTHEME_Blt (hdcDst, dstSize.x-sm.cxRightWidth, dstSize.y-sm.cyBottomHeight, 
+                         sm.cxRightWidth, sm.cyBottomHeight,
+                         hdcSrc, rcSrc.right-sm.cxRightWidth, rcSrc.bottom-sm.cyBottomHeight, 
+                         transparent, transparentcolor)) {
             hr = HRESULT_FROM_WIN32(GetLastError());
             goto draw_error; 
         }
 
-        if(sizingtype == ST_TILE) {
-            FIXME("Tile\n");
-            sizingtype = ST_STRETCH; /* Just use stretch for now */
-        }
-        if(sizingtype == ST_STRETCH) {
+        if ((sizingtype == ST_STRETCH) || (sizingtype == ST_TILE)) {
             int destCenterWidth  = dstSize.x - (sm.cxLeftWidth + sm.cxRightWidth);
             int srcCenterWidth   = srcSize.x - (sm.cxLeftWidth + sm.cxRightWidth);
             int destCenterHeight = dstSize.y - (sm.cyTopHeight + sm.cyBottomHeight);
@@ -531,28 +707,41 @@ static HRESULT UXTHEME_DrawImageBackground(HTHEME hTheme, HDC hdc, int iPartId,
 
             if(destCenterWidth > 0) {
                 /* Center top */
-                if(!StretchBlt(hdcDst, sm.cxLeftWidth, 0, destCenterWidth, sm.cyTopHeight,
-                               hdcSrc, rcSrc.left+sm.cxLeftWidth, rcSrc.top, srcCenterWidth, sm.cyTopHeight, SRCCOPY)) {
+                if(!UXTHEME_SizedBlt (hdcDst, sm.cxLeftWidth, 0, 
+                                      destCenterWidth, sm.cyTopHeight,
+                                      hdcSrc, rcSrc.left+sm.cxLeftWidth, rcSrc.top, 
+                                      srcCenterWidth, sm.cyTopHeight, 
+                                      sizingtype, transparent, transparentcolor)) {
                     hr = HRESULT_FROM_WIN32(GetLastError());
                     goto draw_error; 
                 }
                 /* Center bottom */
-                if(!StretchBlt(hdcDst, sm.cxLeftWidth, dstSize.y-sm.cyBottomHeight, destCenterWidth, sm.cyBottomHeight,
-                               hdcSrc, rcSrc.left+sm.cxLeftWidth, rcSrc.bottom-sm.cyBottomHeight, srcCenterWidth, sm.cyTopHeight, SRCCOPY)) {
+                if(!UXTHEME_SizedBlt (hdcDst, sm.cxLeftWidth, dstSize.y-sm.cyBottomHeight, 
+                                      destCenterWidth, sm.cyBottomHeight,
+                                      hdcSrc, rcSrc.left+sm.cxLeftWidth, rcSrc.bottom-sm.cyBottomHeight, 
+                                      srcCenterWidth, sm.cyBottomHeight, 
+                                      sizingtype, transparent, transparentcolor)) {
                     hr = HRESULT_FROM_WIN32(GetLastError());
                     goto draw_error; 
                 }
             }
             if(destCenterHeight > 0) {
                 /* Left center */
-                if(!StretchBlt(hdcDst, 0, sm.cyTopHeight, sm.cxLeftWidth, destCenterHeight,
-                           hdcSrc, rcSrc.left, rcSrc.top+sm.cyTopHeight, sm.cxLeftWidth, srcCenterHeight, SRCCOPY)) {
+                if(!UXTHEME_SizedBlt (hdcDst, 0, sm.cyTopHeight, 
+                                      sm.cxLeftWidth, destCenterHeight,
+                                      hdcSrc, rcSrc.left, rcSrc.top+sm.cyTopHeight, 
+                                      sm.cxLeftWidth, srcCenterHeight, 
+                                      sizingtype, 
+                                      transparent, transparentcolor)) {
                     hr = HRESULT_FROM_WIN32(GetLastError());
                     goto draw_error; 
                 }
                 /* Right center */
-                if(!StretchBlt(hdcDst, dstSize.x-sm.cxRightWidth, sm.cyTopHeight, sm.cxRightWidth, destCenterHeight,
-                               hdcSrc, rcSrc.right-sm.cxRightWidth, rcSrc.top+sm.cyTopHeight, sm.cxRightWidth, srcCenterHeight, SRCCOPY)) {
+                if(!UXTHEME_SizedBlt (hdcDst, dstSize.x-sm.cxRightWidth, sm.cyTopHeight, 
+                                      sm.cxRightWidth, destCenterHeight,
+                                      hdcSrc, rcSrc.right-sm.cxRightWidth, rcSrc.top+sm.cyTopHeight, 
+                                      sm.cxRightWidth, srcCenterHeight, 
+                                      sizingtype, transparent, transparentcolor)) {
                     hr = HRESULT_FROM_WIN32(GetLastError());
                     goto draw_error; 
                 }
@@ -562,8 +751,11 @@ static HRESULT UXTHEME_DrawImageBackground(HTHEME hTheme, HDC hdc, int iPartId,
                 GetThemeBool(hTheme, iPartId, iStateId, TMT_BORDERONLY, &borderonly);
                 if(!borderonly) {
                     /* Center */
-                    if(!StretchBlt(hdcDst, sm.cxLeftWidth, sm.cyTopHeight, destCenterWidth, destCenterHeight,
-                                   hdcSrc, rcSrc.left+sm.cxLeftWidth, rcSrc.top+sm.cyTopHeight, srcCenterWidth, srcCenterHeight, SRCCOPY)) {
+                    if(!UXTHEME_SizedBlt (hdcDst, sm.cxLeftWidth, sm.cyTopHeight, 
+                                          destCenterWidth, destCenterHeight,
+                                          hdcSrc, rcSrc.left+sm.cxLeftWidth, rcSrc.top+sm.cyTopHeight, 
+                                          srcCenterWidth, srcCenterHeight, 
+                                          sizingtype, transparent, transparentcolor)) {
                         hr = HRESULT_FROM_WIN32(GetLastError());
                         goto draw_error; 
                     }
@@ -571,20 +763,10 @@ static HRESULT UXTHEME_DrawImageBackground(HTHEME hTheme, HDC hdc, int iPartId,
             }
         }
 
-        if(!UXTHEME_Blt(hdc, rcDst.left, rcDst.top, dstSize.x, dstSize.y,
-                        hdcDst, 0, 0,
-                        transparent, transparentcolor))
-            hr = HRESULT_FROM_WIN32(GetLastError());
-
 draw_error:
-        if(hdcDst) {
-            SelectObject(hdcDst, oldDst);
-            DeleteDC(hdcDst);
-        }
-        if(bmpDst) DeleteObject(bmpDst);
+        SetViewportOrgEx (hdcDst, org.x, org.y, NULL);
     }
     SelectObject(hdcSrc, oldSrc);
-    DeleteObject(bmpSrc);
     DeleteDC(hdcSrc);
     CopyRect(pRect, &rcDst);
     return hr;
@@ -751,6 +933,9 @@ HRESULT WINAPI DrawThemeBackgroundEx(HTHEME hTheme, HDC hdc, int iPartId,
     if(!hTheme)
         return E_HANDLE;
 
+    GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_BGTYPE, &bgtype);
+    if (bgtype == BT_NONE) return S_OK;
+
     /* Ensure we have a DTBGOPTS structure available, simplifies some of the code */
     opts = pOptions;
     if(!opts) opts = &defaultOpts;
@@ -765,7 +950,6 @@ HRESULT WINAPI DrawThemeBackgroundEx(HTHEME hTheme, HDC hdc, int iPartId,
     }
     CopyRect(&rt, pRect);
 
-    GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_BGTYPE, &bgtype);
     if(bgtype == BT_IMAGEFILE)
         hr = UXTHEME_DrawImageBackground(hTheme, hdc, iPartId, iStateId, &rt, opts);
     else if(bgtype == BT_BORDERFILL)
@@ -787,19 +971,557 @@ HRESULT WINAPI DrawThemeBackgroundEx(HTHEME hTheme, HDC hdc, int iPartId,
     return hr;
 }
 
+/*
+ * DrawThemeEdge() implementation
+ *
+ * Since it basically is DrawEdge() with different colors, I copied its code
+ * from user32's uitools.c.
+ */
+
+enum
+{
+    EDGE_LIGHT,
+    EDGE_HIGHLIGHT,
+    EDGE_SHADOW,
+    EDGE_DARKSHADOW,
+    EDGE_FILL,
+
+    EDGE_WINDOW,
+    EDGE_WINDOWFRAME,
+
+    EDGE_NUMCOLORS
+};
+
+static const struct 
+{
+    int themeProp;
+    int sysColor;
+} EdgeColorMap[EDGE_NUMCOLORS] = {
+    {TMT_EDGELIGHTCOLOR,                  COLOR_3DLIGHT},
+    {TMT_EDGEHIGHLIGHTCOLOR,              COLOR_BTNHIGHLIGHT},
+    {TMT_EDGESHADOWCOLOR,                 COLOR_BTNSHADOW},
+    {TMT_EDGEDKSHADOWCOLOR,               COLOR_3DDKSHADOW},
+    {TMT_EDGEFILLCOLOR,                   COLOR_BTNFACE},
+    {-1,                                  COLOR_WINDOW},
+    {-1,                                  COLOR_WINDOWFRAME}
+};
+
+static const signed char LTInnerNormal[] = {
+    -1,           -1,                 -1,                 -1,
+    -1,           EDGE_HIGHLIGHT,     EDGE_HIGHLIGHT,     -1,
+    -1,           EDGE_DARKSHADOW,    EDGE_DARKSHADOW,    -1,
+    -1,           -1,                 -1,                 -1
+};
+
+static const signed char LTOuterNormal[] = {
+    -1,                 EDGE_LIGHT,     EDGE_SHADOW, -1,
+    EDGE_HIGHLIGHT,     EDGE_LIGHT,     EDGE_SHADOW, -1,
+    EDGE_DARKSHADOW,    EDGE_LIGHT,     EDGE_SHADOW, -1,
+    -1,                 EDGE_LIGHT,     EDGE_SHADOW, -1
+};
+
+static const signed char RBInnerNormal[] = {
+    -1,           -1,                 -1,               -1,
+    -1,           EDGE_SHADOW,        EDGE_SHADOW,      -1,
+    -1,           EDGE_LIGHT,         EDGE_LIGHT,       -1,
+    -1,           -1,                 -1,               -1
+};
+
+static const signed char RBOuterNormal[] = {
+    -1,               EDGE_DARKSHADOW,  EDGE_HIGHLIGHT, -1,
+    EDGE_SHADOW,      EDGE_DARKSHADOW,  EDGE_HIGHLIGHT, -1,
+    EDGE_LIGHT,       EDGE_DARKSHADOW,  EDGE_HIGHLIGHT, -1,
+    -1,               EDGE_DARKSHADOW,  EDGE_HIGHLIGHT, -1
+};
+
+static const signed char LTInnerSoft[] = {
+    -1,                  -1,                -1,               -1,
+    -1,                  EDGE_LIGHT,        EDGE_LIGHT,       -1,
+    -1,                  EDGE_SHADOW,       EDGE_SHADOW,      -1,
+    -1,                  -1,                -1,               -1
+};
+
+static const signed char LTOuterSoft[] = {
+    -1,               EDGE_HIGHLIGHT, EDGE_DARKSHADOW, -1,
+    EDGE_LIGHT,       EDGE_HIGHLIGHT, EDGE_DARKSHADOW, -1,
+    EDGE_SHADOW,      EDGE_HIGHLIGHT, EDGE_DARKSHADOW, -1,
+    -1,               EDGE_HIGHLIGHT, EDGE_DARKSHADOW, -1
+};
+
+#define RBInnerSoft RBInnerNormal   /* These are the same */
+#define RBOuterSoft RBOuterNormal
+
+static const signed char LTRBOuterMono[] = {
+    -1,           EDGE_WINDOWFRAME, EDGE_WINDOWFRAME, EDGE_WINDOWFRAME,
+    EDGE_WINDOW,  EDGE_WINDOWFRAME, EDGE_WINDOWFRAME, EDGE_WINDOWFRAME,
+    EDGE_WINDOW,  EDGE_WINDOWFRAME, EDGE_WINDOWFRAME, EDGE_WINDOWFRAME,
+    EDGE_WINDOW,  EDGE_WINDOWFRAME, EDGE_WINDOWFRAME, EDGE_WINDOWFRAME,
+};
+
+static const signed char LTRBInnerMono[] = {
+    -1, -1,           -1,           -1,
+    -1, EDGE_WINDOW,  EDGE_WINDOW,  EDGE_WINDOW,
+    -1, EDGE_WINDOW,  EDGE_WINDOW,  EDGE_WINDOW,
+    -1, EDGE_WINDOW,  EDGE_WINDOW,  EDGE_WINDOW,
+};
+
+static const signed char LTRBOuterFlat[] = {
+    -1,                 EDGE_SHADOW, EDGE_SHADOW, EDGE_SHADOW,
+    EDGE_FILL,          EDGE_SHADOW, EDGE_SHADOW, EDGE_SHADOW,
+    EDGE_FILL,          EDGE_SHADOW, EDGE_SHADOW, EDGE_SHADOW,
+    EDGE_FILL,          EDGE_SHADOW, EDGE_SHADOW, EDGE_SHADOW,
+};
+
+static const signed char LTRBInnerFlat[] = {
+    -1, -1,               -1,               -1,
+    -1, EDGE_FILL,        EDGE_FILL,        EDGE_FILL,
+    -1, EDGE_FILL,        EDGE_FILL,        EDGE_FILL,
+    -1, EDGE_FILL,        EDGE_FILL,        EDGE_FILL,
+};
+
+static COLORREF get_edge_color (int edgeType, HTHEME theme, int part, int state)
+{
+    COLORREF col;
+    if ((EdgeColorMap[edgeType].themeProp == -1)
+        || FAILED (GetThemeColor (theme, part, state, 
+            EdgeColorMap[edgeType].themeProp, &col)))
+        col = GetSysColor (EdgeColorMap[edgeType].sysColor);
+    return col;
+}
+
+static inline HPEN get_edge_pen (int edgeType, HTHEME theme, int part, int state)
+{
+    return CreatePen (PS_SOLID, 1, get_edge_color (edgeType, theme, part, state));
+}
+
+static inline HBRUSH get_edge_brush (int edgeType, HTHEME theme, int part, int state)
+{
+    return CreateSolidBrush (get_edge_color (edgeType, theme, part, state));
+}
+
+/***********************************************************************
+ *           draw_diag_edge
+ *
+ * Same as DrawEdge invoked with BF_DIAGONAL
+ */
+static HRESULT draw_diag_edge (HDC hdc, HTHEME theme, int part, int state,
+                               const RECT* rc, UINT uType, 
+                               UINT uFlags, LPRECT contentsRect)
+{
+    POINT Points[4];
+    signed char InnerI, OuterI;
+    HPEN InnerPen, OuterPen;
+    POINT SavePoint;
+    HPEN SavePen;
+    int spx, spy;
+    int epx, epy;
+    int Width = rc->right - rc->left;
+    int Height= rc->bottom - rc->top;
+    int SmallDiam = Width > Height ? Height : Width;
+    HRESULT retval = (((uType & BDR_INNER) == BDR_INNER
+                       || (uType & BDR_OUTER) == BDR_OUTER)
+                      && !(uFlags & (BF_FLAT|BF_MONO)) ) ? E_FAIL : S_OK;
+    int add = (LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0)
+            + (LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0);
+
+    /* Init some vars */
+    OuterPen = InnerPen = (HPEN)GetStockObject(NULL_PEN);
+    SavePen = (HPEN)SelectObject(hdc, InnerPen);
+    spx = spy = epx = epy = 0; /* Satisfy the compiler... */
+
+    /* Determine the colors of the edges */
+    if(uFlags & BF_MONO)
+    {
+        InnerI = LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)];
+        OuterI = LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)];
+    }
+    else if(uFlags & BF_FLAT)
+    {
+        InnerI = LTRBInnerFlat[uType & (BDR_INNER|BDR_OUTER)];
+        OuterI = LTRBOuterFlat[uType & (BDR_INNER|BDR_OUTER)];
+    }
+    else if(uFlags & BF_SOFT)
+    {
+        if(uFlags & BF_BOTTOM)
+        {
+            InnerI = RBInnerSoft[uType & (BDR_INNER|BDR_OUTER)];
+            OuterI = RBOuterSoft[uType & (BDR_INNER|BDR_OUTER)];
+        }
+        else
+        {
+            InnerI = LTInnerSoft[uType & (BDR_INNER|BDR_OUTER)];
+            OuterI = LTOuterSoft[uType & (BDR_INNER|BDR_OUTER)];
+        }
+    }
+    else
+    {
+        if(uFlags & BF_BOTTOM)
+        {
+            InnerI = RBInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
+            OuterI = RBOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
+        }
+        else
+        {
+            InnerI = LTInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
+            OuterI = LTOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
+        }
+    }
+
+    if(InnerI != -1) InnerPen = get_edge_pen (InnerI, theme, part, state);
+    if(OuterI != -1) OuterPen = get_edge_pen (OuterI, theme, part, state);
+
+    MoveToEx(hdc, 0, 0, &SavePoint);
+
+    /* Don't ask me why, but this is what is visible... */
+    /* This must be possible to do much simpler, but I fail to */
+    /* see the logic in the MS implementation (sigh...). */
+    /* So, this might look a bit brute force here (and it is), but */
+    /* it gets the job done;) */
+
+    switch(uFlags & BF_RECT)
+    {
+    case 0:
+    case BF_LEFT:
+    case BF_BOTTOM:
+    case BF_BOTTOMLEFT:
+        /* Left bottom endpoint */
+        epx = rc->left-1;
+        spx = epx + SmallDiam;
+        epy = rc->bottom;
+        spy = epy - SmallDiam;
+        break;
+
+    case BF_TOPLEFT:
+    case BF_BOTTOMRIGHT:
+        /* Left top endpoint */
+        epx = rc->left-1;
+        spx = epx + SmallDiam;
+        epy = rc->top-1;
+        spy = epy + SmallDiam;
+        break;
+
+    case BF_TOP:
+    case BF_RIGHT:
+    case BF_TOPRIGHT:
+    case BF_RIGHT|BF_LEFT:
+    case BF_RIGHT|BF_LEFT|BF_TOP:
+    case BF_BOTTOM|BF_TOP:
+    case BF_BOTTOM|BF_TOP|BF_LEFT:
+    case BF_BOTTOMRIGHT|BF_LEFT:
+    case BF_BOTTOMRIGHT|BF_TOP:
+    case BF_RECT:
+        /* Right top endpoint */
+        spx = rc->left;
+        epx = spx + SmallDiam;
+        spy = rc->bottom-1;
+        epy = spy - SmallDiam;
+        break;
+    }
+
+    MoveToEx(hdc, spx, spy, NULL);
+    SelectObject(hdc, OuterPen);
+    LineTo(hdc, epx, epy);
+
+    SelectObject(hdc, InnerPen);
+
+    switch(uFlags & (BF_RECT|BF_DIAGONAL))
+    {
+    case BF_DIAGONAL_ENDBOTTOMLEFT:
+    case (BF_DIAGONAL|BF_BOTTOM):
+    case BF_DIAGONAL:
+    case (BF_DIAGONAL|BF_LEFT):
+        MoveToEx(hdc, spx-1, spy, NULL);
+        LineTo(hdc, epx, epy-1);
+        Points[0].x = spx-add;
+        Points[0].y = spy;
+        Points[1].x = rc->left;
+        Points[1].y = rc->top;
+        Points[2].x = epx+1;
+        Points[2].y = epy-1-add;
+        Points[3] = Points[2];
+        break;
+
+    case BF_DIAGONAL_ENDBOTTOMRIGHT:
+        MoveToEx(hdc, spx-1, spy, NULL);
+        LineTo(hdc, epx, epy+1);
+        Points[0].x = spx-add;
+        Points[0].y = spy;
+        Points[1].x = rc->left;
+        Points[1].y = rc->bottom-1;
+        Points[2].x = epx+1;
+        Points[2].y = epy+1+add;
+        Points[3] = Points[2];
+        break;
+
+    case (BF_DIAGONAL|BF_BOTTOM|BF_RIGHT|BF_TOP):
+    case (BF_DIAGONAL|BF_BOTTOM|BF_RIGHT|BF_TOP|BF_LEFT):
+    case BF_DIAGONAL_ENDTOPRIGHT:
+    case (BF_DIAGONAL|BF_RIGHT|BF_TOP|BF_LEFT):
+        MoveToEx(hdc, spx+1, spy, NULL);
+        LineTo(hdc, epx, epy+1);
+        Points[0].x = epx-1;
+        Points[0].y = epy+1+add;
+        Points[1].x = rc->right-1;
+        Points[1].y = rc->top+add;
+        Points[2].x = rc->right-1;
+        Points[2].y = rc->bottom-1;
+        Points[3].x = spx+add;
+        Points[3].y = spy;
+        break;
+
+    case BF_DIAGONAL_ENDTOPLEFT:
+        MoveToEx(hdc, spx, spy-1, NULL);
+        LineTo(hdc, epx+1, epy);
+        Points[0].x = epx+1+add;
+        Points[0].y = epy+1;
+        Points[1].x = rc->right-1;
+        Points[1].y = rc->top;
+        Points[2].x = rc->right-1;
+        Points[2].y = rc->bottom-1-add;
+        Points[3].x = spx;
+        Points[3].y = spy-add;
+        break;
+
+    case (BF_DIAGONAL|BF_TOP):
+    case (BF_DIAGONAL|BF_BOTTOM|BF_TOP):
+    case (BF_DIAGONAL|BF_BOTTOM|BF_TOP|BF_LEFT):
+        MoveToEx(hdc, spx+1, spy-1, NULL);
+        LineTo(hdc, epx, epy);
+        Points[0].x = epx-1;
+        Points[0].y = epy+1;
+        Points[1].x = rc->right-1;
+        Points[1].y = rc->top;
+        Points[2].x = rc->right-1;
+        Points[2].y = rc->bottom-1-add;
+        Points[3].x = spx+add;
+        Points[3].y = spy-add;
+        break;
+
+    case (BF_DIAGONAL|BF_RIGHT):
+    case (BF_DIAGONAL|BF_RIGHT|BF_LEFT):
+    case (BF_DIAGONAL|BF_RIGHT|BF_LEFT|BF_BOTTOM):
+        MoveToEx(hdc, spx, spy, NULL);
+        LineTo(hdc, epx-1, epy+1);
+        Points[0].x = spx;
+        Points[0].y = spy;
+        Points[1].x = rc->left;
+        Points[1].y = rc->top+add;
+        Points[2].x = epx-1-add;
+        Points[2].y = epy+1+add;
+        Points[3] = Points[2];
+        break;
+    }
+
+    /* Fill the interior if asked */
+    if((uFlags & BF_MIDDLE) && retval)
+    {
+        HBRUSH hbsave;
+        HBRUSH hb = get_edge_brush ((uFlags & BF_MONO) ? EDGE_WINDOW : EDGE_FILL, 
+            theme, part, state);
+        HPEN hpsave;
+        HPEN hp = get_edge_pen ((uFlags & BF_MONO) ? EDGE_WINDOW : EDGE_FILL, 
+            theme, part, state);
+        hbsave = (HBRUSH)SelectObject(hdc, hb);
+        hpsave = (HPEN)SelectObject(hdc, hp);
+        Polygon(hdc, Points, 4);
+        SelectObject(hdc, hbsave);
+        SelectObject(hdc, hpsave);
+        DeleteObject (hp);
+        DeleteObject (hb);
+    }
+
+    /* Adjust rectangle if asked */
+    if(uFlags & BF_ADJUST)
+    {
+        *contentsRect = *rc;
+        if(uFlags & BF_LEFT)   contentsRect->left   += add;
+        if(uFlags & BF_RIGHT)  contentsRect->right  -= add;
+        if(uFlags & BF_TOP)    contentsRect->top    += add;
+        if(uFlags & BF_BOTTOM) contentsRect->bottom -= add;
+    }
+
+    /* Cleanup */
+    SelectObject(hdc, SavePen);
+    MoveToEx(hdc, SavePoint.x, SavePoint.y, NULL);
+    if(InnerI != -1) DeleteObject (InnerPen);
+    if(OuterI != -1) DeleteObject (OuterPen);
+
+    return retval;
+}
+
+/***********************************************************************
+ *           draw_rect_edge
+ *
+ * Same as DrawEdge invoked without BF_DIAGONAL
+ */
+static HRESULT draw_rect_edge (HDC hdc, HTHEME theme, int part, int state,
+                               const RECT* rc, UINT uType, 
+                               UINT uFlags, LPRECT contentsRect)
+{
+    signed char LTInnerI, LTOuterI;
+    signed char RBInnerI, RBOuterI;
+    HPEN LTInnerPen, LTOuterPen;
+    HPEN RBInnerPen, RBOuterPen;
+    RECT InnerRect = *rc;
+    POINT SavePoint;
+    HPEN SavePen;
+    int LBpenplus = 0;
+    int LTpenplus = 0;
+    int RTpenplus = 0;
+    int RBpenplus = 0;
+    HRESULT retval = (((uType & BDR_INNER) == BDR_INNER
+                       || (uType & BDR_OUTER) == BDR_OUTER)
+                      && !(uFlags & (BF_FLAT|BF_MONO)) ) ? E_FAIL : S_OK;
+
+    /* Init some vars */
+    LTInnerPen = LTOuterPen = RBInnerPen = RBOuterPen = (HPEN)GetStockObject(NULL_PEN);
+    SavePen = (HPEN)SelectObject(hdc, LTInnerPen);
+
+    /* Determine the colors of the edges */
+    if(uFlags & BF_MONO)
+    {
+        LTInnerI = RBInnerI = LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)];
+        LTOuterI = RBOuterI = LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)];
+    }
+    else if(uFlags & BF_FLAT)
+    {
+        LTInnerI = RBInnerI = LTRBInnerFlat[uType & (BDR_INNER|BDR_OUTER)];
+        LTOuterI = RBOuterI = LTRBOuterFlat[uType & (BDR_INNER|BDR_OUTER)];
+
+        if( LTInnerI != -1 ) LTInnerI = RBInnerI = COLOR_BTNFACE;
+    }
+    else if(uFlags & BF_SOFT)
+    {
+        LTInnerI = LTInnerSoft[uType & (BDR_INNER|BDR_OUTER)];
+        LTOuterI = LTOuterSoft[uType & (BDR_INNER|BDR_OUTER)];
+        RBInnerI = RBInnerSoft[uType & (BDR_INNER|BDR_OUTER)];
+        RBOuterI = RBOuterSoft[uType & (BDR_INNER|BDR_OUTER)];
+    }
+    else
+    {
+        LTInnerI = LTInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
+        LTOuterI = LTOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
+        RBInnerI = RBInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
+        RBOuterI = RBOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
+    }
+
+    if((uFlags & BF_BOTTOMLEFT) == BF_BOTTOMLEFT)   LBpenplus = 1;
+    if((uFlags & BF_TOPRIGHT) == BF_TOPRIGHT)       RTpenplus = 1;
+    if((uFlags & BF_BOTTOMRIGHT) == BF_BOTTOMRIGHT) RBpenplus = 1;
+    if((uFlags & BF_TOPLEFT) == BF_TOPLEFT)         LTpenplus = 1;
+
+    if(LTInnerI != -1) LTInnerPen = get_edge_pen (LTInnerI, theme, part, state);
+    if(LTOuterI != -1) LTOuterPen = get_edge_pen (LTOuterI, theme, part, state);
+    if(RBInnerI != -1) RBInnerPen = get_edge_pen (RBInnerI, theme, part, state);
+    if(RBOuterI != -1) RBOuterPen = get_edge_pen (RBOuterI, theme, part, state);
+
+    MoveToEx(hdc, 0, 0, &SavePoint);
+
+    /* Draw the outer edge */
+    SelectObject(hdc, LTOuterPen);
+    if(uFlags & BF_TOP)
+    {
+        MoveToEx(hdc, InnerRect.left, InnerRect.top, NULL);
+        LineTo(hdc, InnerRect.right, InnerRect.top);
+    }
+    if(uFlags & BF_LEFT)
+    {
+        MoveToEx(hdc, InnerRect.left, InnerRect.top, NULL);
+        LineTo(hdc, InnerRect.left, InnerRect.bottom);
+    }
+    SelectObject(hdc, RBOuterPen);
+    if(uFlags & BF_BOTTOM)
+    {
+        MoveToEx(hdc, InnerRect.right-1, InnerRect.bottom-1, NULL);
+        LineTo(hdc, InnerRect.left-1, InnerRect.bottom-1);
+    }
+    if(uFlags & BF_RIGHT)
+    {
+        MoveToEx(hdc, InnerRect.right-1, InnerRect.bottom-1, NULL);
+        LineTo(hdc, InnerRect.right-1, InnerRect.top-1);
+    }
+
+    /* Draw the inner edge */
+    SelectObject(hdc, LTInnerPen);
+    if(uFlags & BF_TOP)
+    {
+        MoveToEx(hdc, InnerRect.left+LTpenplus, InnerRect.top+1, NULL);
+        LineTo(hdc, InnerRect.right-RTpenplus, InnerRect.top+1);
+    }
+    if(uFlags & BF_LEFT)
+    {
+        MoveToEx(hdc, InnerRect.left+1, InnerRect.top+LTpenplus, NULL);
+        LineTo(hdc, InnerRect.left+1, InnerRect.bottom-LBpenplus);
+    }
+    SelectObject(hdc, RBInnerPen);
+    if(uFlags & BF_BOTTOM)
+    {
+        MoveToEx(hdc, InnerRect.right-1-RBpenplus, InnerRect.bottom-2, NULL);
+        LineTo(hdc, InnerRect.left-1+LBpenplus, InnerRect.bottom-2);
+    }
+    if(uFlags & BF_RIGHT)
+    {
+        MoveToEx(hdc, InnerRect.right-2, InnerRect.bottom-1-RBpenplus, NULL);
+        LineTo(hdc, InnerRect.right-2, InnerRect.top-1+RTpenplus);
+    }
+
+    if( ((uFlags & BF_MIDDLE) && retval) || (uFlags & BF_ADJUST) )
+    {
+        int add = (LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0)
+                + (LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0);
+
+        if(uFlags & BF_LEFT)   InnerRect.left   += add;
+        if(uFlags & BF_RIGHT)  InnerRect.right  -= add;
+        if(uFlags & BF_TOP)    InnerRect.top    += add;
+        if(uFlags & BF_BOTTOM) InnerRect.bottom -= add;
+
+        if((uFlags & BF_MIDDLE) && retval)
+        {
+            HBRUSH br = get_edge_brush ((uFlags & BF_MONO) ? EDGE_WINDOW : EDGE_FILL, 
+                theme, part, state);
+            FillRect(hdc, &InnerRect, br);
+            DeleteObject (br);
+        }
+
+        if(uFlags & BF_ADJUST)
+            *contentsRect = InnerRect;
+    }
+
+    /* Cleanup */
+    SelectObject(hdc, SavePen);
+    MoveToEx(hdc, SavePoint.x, SavePoint.y, NULL);
+    if(LTInnerI != -1) DeleteObject (LTInnerPen);
+    if(LTOuterI != -1) DeleteObject (LTOuterPen);
+    if(RBInnerI != -1) DeleteObject (RBInnerPen);
+    if(RBOuterI != -1) DeleteObject (RBOuterPen);
+    return retval;
+}
+
+
 /***********************************************************************
  *      DrawThemeEdge                                       (UXTHEME.@)
+ *
+ * DrawThemeEdge() is pretty similar to the vanilla DrawEdge() - the
+ * difference is that it does not rely on the system colors alone, but
+ * also allows color specification in the theme.
  */
 HRESULT WINAPI DrawThemeEdge(HTHEME hTheme, HDC hdc, int iPartId,
                              int iStateId, const RECT *pDestRect, UINT uEdge,
                              UINT uFlags, RECT *pContentRect)
 {
-    FIXME("%d %d 0x%08x 0x%08x: stub\n", iPartId, iStateId, uEdge, uFlags);
+    TRACE("%d %d 0x%08x 0x%08x\n", iPartId, iStateId, uEdge, uFlags);
     if(!hTheme)
         return E_HANDLE;
-    return ERROR_CALL_NOT_IMPLEMENTED;
+     
+    if(uFlags & BF_DIAGONAL)
+        return draw_diag_edge (hdc, hTheme, iPartId, iStateId, pDestRect,
+            uEdge, uFlags, pContentRect);
+    else
+        return draw_rect_edge (hdc, hTheme, iPartId, iStateId, pDestRect,
+            uEdge, uFlags, pContentRect);
 }
 
+
 /***********************************************************************
  *      DrawThemeIcon                                       (UXTHEME.@)
  */
@@ -924,15 +1646,34 @@ HRESULT WINAPI GetThemeBackgroundExtent(HTHEME hTheme, HDC hdc, int iPartId,
     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)) {
+        pExtentRect->left = pContentRect->left - margin.cxLeftWidth;
+        pExtentRect->top  = pContentRect->top - margin.cyTopHeight;
+        pExtentRect->right = pContentRect->right + margin.cxRightWidth;
+        pExtentRect->bottom = pContentRect->bottom + margin.cyBottomHeight;
+    } else {
+        /* otherwise, try to determine content rect from the background type and props */
+        int bgtype = BT_BORDERFILL;
+        memcpy(pExtentRect, pContentRect, sizeof(RECT));
+
+        GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_BGTYPE, &bgtype);
+        if(bgtype == BT_BORDERFILL) {
+            int bordersize = 1;
+    
+            GetThemeInt(hTheme, iPartId, iStateId, TMT_BORDERSIZE, &bordersize);
+            InflateRect(pExtentRect, bordersize, bordersize);
+        } else if ((bgtype == BT_IMAGEFILE)
+                && (SUCCEEDED(hr = GetThemeMargins(hTheme, hdc, iPartId, iStateId, 
+                TMT_SIZINGMARGINS, NULL, &margin)))) {
+            pExtentRect->left = pContentRect->left - margin.cxLeftWidth;
+            pExtentRect->top  = pContentRect->top - margin.cyTopHeight;
+            pExtentRect->right = pContentRect->right + margin.cxRightWidth;
+            pExtentRect->bottom = pContentRect->bottom + margin.cyBottomHeight;
+        }
+        /* If nothing was found, leave unchanged */
     }
-    pExtentRect->left = pContentRect->left - margin.cxLeftWidth;
-    pExtentRect->top  = pContentRect->top - margin.cyTopHeight;
-    pExtentRect->right = pContentRect->right + margin.cxRightWidth;
-    pExtentRect->bottom = pContentRect->bottom + margin.cyBottomHeight;
 
     TRACE("left:%ld,top:%ld,right:%ld,bottom:%ld\n", pExtentRect->left, pExtentRect->top, pExtentRect->right, pExtentRect->bottom);
 
@@ -976,6 +1717,26 @@ HRESULT WINAPI GetThemeBackgroundRegion(HTHEME hTheme, HDC hdc, int iPartId,
     return hr;
 }
 
+/* compute part size for "borderfill" backgrounds */
+HRESULT get_border_background_size (HTHEME hTheme, int iPartId,
+                                    int iStateId, THEMESIZE eSize, POINT* psz)
+{
+    HRESULT hr = S_OK;
+    int bordersize = 1;
+
+    if (SUCCEEDED (hr = GetThemeInt(hTheme, iPartId, iStateId, TMT_BORDERSIZE, 
+        &bordersize)))
+    {
+        psz->x = psz->y = 2*bordersize;
+        if (eSize != TS_MIN)
+        {
+            psz->x++;
+            psz->y++; 
+        }
+    }
+    return hr;
+}
+
 /***********************************************************************
  *      GetThemePartSize                                    (UXTHEME.@)
  */
@@ -983,10 +1744,28 @@ HRESULT WINAPI GetThemePartSize(HTHEME hTheme, HDC hdc, int iPartId,
                                 int iStateId, RECT *prc, THEMESIZE eSize,
                                 SIZE *psz)
 {
-    FIXME("%d %d %d: stub\n", iPartId, iStateId, eSize);
+    int bgtype = BT_BORDERFILL;
+    HRESULT hr = S_OK;
+    POINT size = {1, 1};
+
     if(!hTheme)
         return E_HANDLE;
-    return ERROR_CALL_NOT_IMPLEMENTED;
+
+    GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_BGTYPE, &bgtype);
+    if (bgtype == BT_NONE)
+        /* do nothing */;
+    else if(bgtype == BT_IMAGEFILE)
+        hr = get_image_part_size (hTheme, hdc, iPartId, iStateId, prc, eSize, &size);
+    else if(bgtype == BT_BORDERFILL)
+        hr = get_border_background_size (hTheme, iPartId, iStateId, eSize, &size);
+    else {
+        FIXME("Unknown background type\n");
+        /* This should never happen, and hence I don't know what to return */
+        hr = E_FAIL;
+    }
+    psz->cx = size.x;
+    psz->cy = size.y;
+    return hr;
 }
 
 
@@ -1070,8 +1849,28 @@ HRESULT WINAPI GetThemeTextMetrics(HTHEME hTheme, HDC hdc, int iPartId,
 BOOL WINAPI IsThemeBackgroundPartiallyTransparent(HTHEME hTheme, int iPartId,
                                                   int iStateId)
 {
-    BOOL transparent = FALSE;
+    int bgtype = BT_BORDERFILL;
+    RECT rect = {0, 0, 0, 0};
+    HBITMAP bmpSrc;
+    RECT rcSrc;
+    BOOL hasAlpha;
+    INT transparent;
+    COLORREF transparentcolor;
+
     TRACE("(%d,%d)\n", iPartId, iStateId);
-    GetThemeBool(hTheme, iPartId, iStateId, TMT_TRANSPARENT, &transparent);
-    return transparent;
+
+    if(!hTheme)
+        return FALSE;
+
+    GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_BGTYPE, &bgtype);
+
+    if (bgtype != BT_IMAGEFILE) return FALSE;
+
+    if(FAILED (UXTHEME_LoadImage (hTheme, 0, iPartId, iStateId, &rect, FALSE, 
+                                  &bmpSrc, &rcSrc, &hasAlpha))) 
+        return FALSE;
+
+    get_transparency (hTheme, iPartId, iStateId, hasAlpha, &transparent,
+        &transparentcolor, FALSE);
+    return (transparent != ALPHABLEND_NONE);
 }
index e1e20d6..f65a8ba 100644 (file)
@@ -45,9 +45,10 @@ 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;
+extern int alphaBlendMode;
 
 #define MSSTYLES_VERSION 0x0003
 
@@ -214,6 +215,13 @@ void MSSTYLES_CloseThemeFile(PTHEME_FILE tf)
                     HeapFree(GetProcessHeap(), 0, pcls);
                 }
             }
+            while (tf->images)
+            {
+                PTHEME_IMAGE img = tf->images;
+                tf->images = img->next;
+                DeleteObject (img->image);
+                HeapFree (GetProcessHeap(), 0, img);
+            }
             HeapFree(GetProcessHeap(), 0, tf);
         }
     }
@@ -224,7 +232,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 +241,7 @@ HRESULT MSSTYLES_SetActiveTheme(PTHEME_FILE tf)
     {
        tfActiveTheme->dwRefCount++;
        if(!tfActiveTheme->classes)
-           MSSTYLES_ParseThemeIni(tfActiveTheme);
+           MSSTYLES_ParseThemeIni(tfActiveTheme, setMetrics);
     }
     return S_OK;
 }
@@ -664,7 +672,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,9 +717,9 @@ 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);
+                       SystemParametersInfoW (SPI_SETFLATMENU, 0, (PVOID)(INT_PTR)flatMenus, 0);
                    }
                     /* Catch all metrics, including colors */
                     MSSTYLES_AddMetric(tf, iPropertyPrimitive, iPropertyId, lpValue, dwValueLen);
@@ -720,7 +728,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;
         }
@@ -868,10 +876,43 @@ PTHEME_PROPERTY MSSTYLES_FindProperty(PTHEME_CLASS tc, int iPartId, int iStateId
     return NULL;
 }
 
-HBITMAP MSSTYLES_LoadBitmap(HDC hdc, PTHEME_CLASS tc, LPCWSTR lpFilename)
+/* Prepare a bitmap to be used for alpha blending */
+static BOOL prepare_alpha (HBITMAP bmp, BOOL* hasAlpha)
+{
+    DIBSECTION dib;
+    int n;
+    BYTE* p;
+
+    *hasAlpha = FALSE;
+
+    if (!bmp || GetObjectW( bmp, sizeof(dib), &dib ) != sizeof(dib))
+        return FALSE;
+
+    if(dib.dsBm.bmBitsPixel != 32)
+        /* nothing to do */
+        return TRUE;
+
+    *hasAlpha = TRUE;
+    p = (BYTE*)dib.dsBm.bmBits;
+    n = abs(dib.dsBmih.biHeight) * dib.dsBmih.biWidth;
+    /* AlphaBlend() wants premultiplied alpha, so do that now */
+    while (n-- > 0)
+    {
+        int a = p[3]+1;
+        p[0] = (p[0] * a) >> 8;
+        p[1] = (p[1] * a) >> 8;
+        p[2] = (p[2] * a) >> 8;
+        p += 4;
+    }
+
+    return TRUE;
+}
+
+HBITMAP MSSTYLES_LoadBitmap (PTHEME_CLASS tc, LPCWSTR lpFilename, BOOL* hasAlpha)
 {
     WCHAR szFile[MAX_PATH];
     LPWSTR tmp;
+    PTHEME_IMAGE img;
     lstrcpynW(szFile, lpFilename, sizeof(szFile)/sizeof(szFile[0]));
     tmp = szFile;
     do {
@@ -879,7 +920,30 @@ HBITMAP MSSTYLES_LoadBitmap(HDC hdc, PTHEME_CLASS tc, LPCWSTR lpFilename)
         if(*tmp == '/') *tmp = '_';
         if(*tmp == '.') *tmp = '_';
     } while(*tmp++);
-    return LoadImageW(tc->hTheme, szFile, IMAGE_BITMAP, 0, 0, LR_SHARED|LR_CREATEDIBSECTION);
+
+    /* Try to locate in list of loaded images */
+    img = tc->tf->images;
+    while (img)
+    {
+        if (lstrcmpiW (szFile, img->name) == 0)
+        {
+            TRACE ("found %p %s: %p\n", img, debugstr_w (img->name), img->image);
+            *hasAlpha = img->hasAlpha;
+            return img->image;
+        }
+        img = img->next;
+    }
+    /* Not found? Load from resources */
+    img = HeapAlloc (GetProcessHeap(), 0, sizeof (THEME_IMAGE));
+    img->image = LoadImageW(tc->hTheme, szFile, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
+    prepare_alpha (img->image, hasAlpha);
+    img->hasAlpha = *hasAlpha;
+    /* ...and stow away for later reuse. */
+    lstrcpyW (img->name, szFile);
+    img->next = tc->tf->images;
+    tc->tf->images = img;
+    TRACE ("new %p %s: %p\n", img, debugstr_w (img->name), img->image);
+    return img->image;
 }
 
 BOOL MSSTYLES_GetNextInteger(LPCWSTR lpStringStart, LPCWSTR lpStringEnd, LPCWSTR *lpValEnd, int *value)
index 93e3cd0..76b83f0 100644 (file)
@@ -59,6 +59,14 @@ typedef struct _THEME_CLASS {
     struct _THEME_CLASS *next;
 } THEME_CLASS, *PTHEME_CLASS;
 
+typedef struct _THEME_IMAGE {
+    WCHAR name[MAX_PATH];
+    HBITMAP image;
+    BOOL hasAlpha;
+    
+    struct _THEME_IMAGE *next;
+} THEME_IMAGE, *PTHEME_IMAGE;
+
 typedef struct _THEME_FILE {
     DWORD dwRefCount;
     HMODULE hTheme;
@@ -71,13 +79,14 @@ typedef struct _THEME_FILE {
 
     PTHEME_CLASS classes;
     PTHEME_PROPERTY metrics;
+    PTHEME_IMAGE images;
 } THEME_FILE, *PTHEME_FILE;
 
 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);
@@ -88,7 +97,7 @@ PTHEME_PARTSTATE MSSTYLES_FindPartState(PTHEME_CLASS tc, int iPartId, int iState
 PTHEME_CLASS MSSTYLES_FindClass(PTHEME_FILE tf, LPCWSTR pszAppName, LPCWSTR pszClassName);
 PTHEME_PROPERTY MSSTYLES_FindProperty(PTHEME_CLASS tc, int iPartId, int iStateId, int iPropertyPrimitive, int iPropertyId);
 PTHEME_PROPERTY MSSTYLES_FindMetric(int iPropertyPrimitive, int iPropertyId);
-HBITMAP MSSTYLES_LoadBitmap(HDC hdc, PTHEME_CLASS tc, LPCWSTR lpFilename);
+HBITMAP MSSTYLES_LoadBitmap(PTHEME_CLASS tc, LPCWSTR lpFilename, BOOL* hasAlpha);
 
 HRESULT MSSTYLES_GetPropertyBool(PTHEME_PROPERTY tp, BOOL *pfVal);
 HRESULT MSSTYLES_GetPropertyColor(PTHEME_PROPERTY tp, COLORREF *pColor);
index 4caa8be..4c8bb7f 100644 (file)
@@ -225,6 +225,7 @@ HRESULT WINAPI GetThemeMargins(HTHEME hTheme, HDC hdc, int iPartId,
     PTHEME_PROPERTY tp;
 
     TRACE("(%d, %d, %d)\n", iPartId, iStateId, iPropId);
+    memset (pMargins, 0, sizeof (MARGINS));
     if(!hTheme)
         return E_HANDLE;
 
index 2a5837f..51fc56e 100644 (file)
@@ -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 (RegQueryValueExA (colorKey, SysColorsNames[i], 0,
+                    &type, colorStr, &count) == ERROR_SUCCESS)
+                {
+                    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 (RegQueryValueExW (hKey, bsp->keyName, 0,
+                &type, (LPBYTE)&value, &count) == ERROR_SUCCESS)
+            {
+                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)) {
@@ -695,7 +898,7 @@ HRESULT WINAPI EnumThemes(LPCWSTR pszThemePath, EnumThemeProc callback,
  *     pszSizeName         Theme size to enumerate available colors
  *                         If NULL the default theme size is used
  *     dwColorNum          Color index to retrieve, increment from 0
- *     pszColorName        Output color name
+ *     pszColorNames       Output color names
  *
  * RETURNS
  *     S_OK on success
@@ -703,19 +906,20 @@ HRESULT WINAPI EnumThemes(LPCWSTR pszThemePath, EnumThemeProc callback,
  *          or when pszSizeName does not refer to a valid size
  *
  * NOTES
- * XP fails with E_POINTER when pszColorName points to a buffer smaller then 605
- * characters
+ * XP fails with E_POINTER when pszColorNames points to a buffer smaller than 
+ * sizeof(THEMENAMES).
  *
  * Not very efficient that I'm opening & validating the theme every call, but
  * this is undocumented and almost never called..
  * (and this is how windows works too)
  */
 HRESULT WINAPI EnumThemeColors(LPWSTR pszThemeFileName, LPWSTR pszSizeName,
-                               DWORD dwColorNum, LPWSTR pszColorName)
+                               DWORD dwColorNum, PTHEMENAMES pszColorNames)
 {
     PTHEME_FILE pt;
     HRESULT hr;
     LPWSTR tmp;
+    UINT resourceId = dwColorNum + 1000;
     TRACE("(%s,%s,%ld)\n", debugstr_w(pszThemeFileName),
           debugstr_w(pszSizeName), dwColorNum);
 
@@ -729,7 +933,13 @@ HRESULT WINAPI EnumThemeColors(LPWSTR pszThemeFileName, LPWSTR pszSizeName,
     }
     if(!dwColorNum && *tmp) {
         TRACE("%s\n", debugstr_w(tmp));
-        lstrcpyW(pszColorName, tmp);
+        lstrcpyW(pszColorNames->szName, tmp);
+        LoadStringW (pt->hTheme, resourceId,
+            pszColorNames->szDisplayName,
+            sizeof (pszColorNames->szDisplayName) / sizeof (WCHAR));
+        LoadStringW (pt->hTheme, resourceId+1000,
+            pszColorNames->szTooltip,
+            sizeof (pszColorNames->szTooltip) / sizeof (WCHAR));
     }
     else
         hr = E_PROP_ID_UNSUPPORTED;
@@ -748,7 +958,7 @@ HRESULT WINAPI EnumThemeColors(LPWSTR pszThemeFileName, LPWSTR pszSizeName,
  *     pszColorName        Theme color to enumerate available sizes
  *                         If NULL the default theme color is used
  *     dwSizeNum           Size index to retrieve, increment from 0
- *     pszSizeName         Output size name
+ *     pszSizeNames        Output size names
  *
  * RETURNS
  *     S_OK on success
@@ -756,19 +966,20 @@ HRESULT WINAPI EnumThemeColors(LPWSTR pszThemeFileName, LPWSTR pszSizeName,
  *          or when pszColorName does not refer to a valid color
  *
  * NOTES
- * XP fails with E_POINTER when pszSizeName points to a buffer smaller then 605
- * characters
+ * XP fails with E_POINTER when pszSizeNames points to a buffer smaller than 
+ * sizeof(THEMENAMES).
  *
  * Not very efficient that I'm opening & validating the theme every call, but
  * this is undocumented and almost never called..
  * (and this is how windows works too)
  */
 HRESULT WINAPI EnumThemeSizes(LPWSTR pszThemeFileName, LPWSTR pszColorName,
-                              DWORD dwSizeNum, LPWSTR pszSizeName)
+                              DWORD dwSizeNum, PTHEMENAMES pszSizeNames)
 {
     PTHEME_FILE pt;
     HRESULT hr;
     LPWSTR tmp;
+    UINT resourceId = dwSizeNum + 3000;
     TRACE("(%s,%s,%ld)\n", debugstr_w(pszThemeFileName),
           debugstr_w(pszColorName), dwSizeNum);
 
@@ -782,7 +993,13 @@ HRESULT WINAPI EnumThemeSizes(LPWSTR pszThemeFileName, LPWSTR pszColorName,
     }
     if(!dwSizeNum && *tmp) {
         TRACE("%s\n", debugstr_w(tmp));
-        lstrcpyW(pszSizeName, tmp);
+        lstrcpyW(pszSizeNames->szName, tmp);
+        LoadStringW (pt->hTheme, resourceId,
+            pszSizeNames->szDisplayName,
+            sizeof (pszSizeNames->szDisplayName) / sizeof (WCHAR));
+        LoadStringW (pt->hTheme, resourceId+1000,
+            pszSizeNames->szTooltip,
+            sizeof (pszSizeNames->szTooltip) / sizeof (WCHAR));
     }
     else
         hr = E_PROP_ID_UNSUPPORTED;
index e9757ab..67dd384 100644 (file)
@@ -1,93 +1,93 @@
-# Undocumented functions - Names derived from debug symbols\r
-1  stdcall -noname QueryThemeServices()\r
-2  stdcall -noname OpenThemeFile(wstr wstr wstr ptr long)\r
-3  stdcall -noname CloseThemeFile(ptr)\r
-4  stdcall -noname ApplyTheme(ptr ptr ptr)\r
-7  stdcall -noname GetThemeDefaults(wstr wstr long wstr long)\r
-8  stdcall -noname EnumThemes(wstr ptr ptr)\r
-9  stdcall -noname EnumThemeColors(wstr wstr long wstr)\r
-10 stdcall -noname EnumThemeSizes(wstr wstr long wstr)\r
-11 stdcall -noname ParseThemeIniFile(wstr wstr ptr ptr)\r
-13 stub -noname DrawNCPreview\r
-14 stub -noname RegisterDefaultTheme\r
-15 stub -noname DumpLoadedThemeToTextFile\r
-16 stub -noname OpenThemeDataFromFile\r
-17 stub -noname OpenThemeFileFromData\r
-18 stub -noname GetThemeSysSize96\r
-19 stub -noname GetThemeSysFont96\r
-20 stub -noname SessionAllocate\r
-21 stub -noname SessionFree\r
-22 stub -noname ThemeHooksOn\r
-23 stub -noname ThemeHooksOff\r
-24 stub -noname AreThemeHooksActive\r
-25 stub -noname GetCurrentChangeNumber\r
-26 stub -noname GetNewChangeNumber\r
-27 stub -noname SetGlobalTheme\r
-28 stub -noname GetGlobalTheme\r
-29 stdcall -noname CheckThemeSignature(wstr)\r
-30 stub -noname LoadTheme\r
-31 stub -noname InitUserTheme\r
-32 stub -noname InitUserRegistry\r
-33 stub -noname ReestablishServerConnection\r
-34 stub -noname ThemeHooksInstall\r
-35 stub -noname ThemeHooksRemove\r
-36 stub -noname RefreshThemeForTS\r
-43 stub -noname ClassicGetSystemMetrics\r
-44 stub -noname ClassicSystemParametersInfoA\r
-45 stub -noname ClassicSystemParametersInfoW\r
-46 stub -noname ClassicAdjustWindowRectEx\r
-48 stub -noname GetThemeParseErrorInfo\r
-60 stub -noname CreateThemeDataFromObjects\r
-61 stub -noname OpenThemeDataEx\r
-62 stub -noname ServerClearStockObjects\r
-63 stub -noname MarkSelection\r
-\r
-# Standard functions\r
-@ stdcall CloseThemeData(ptr)\r
-@ stdcall DrawThemeBackground(ptr ptr long long ptr ptr)\r
-@ stdcall DrawThemeBackgroundEx(ptr ptr long long ptr ptr)\r
-@ stdcall DrawThemeEdge(ptr ptr long long ptr long long ptr)\r
-@ stdcall DrawThemeIcon(ptr ptr long long ptr ptr long)\r
-@ stdcall DrawThemeParentBackground(ptr ptr ptr)\r
-@ stdcall DrawThemeText(ptr ptr long long wstr long long long ptr)\r
-@ stdcall EnableThemeDialogTexture(ptr long)\r
-@ stdcall EnableTheming(long)\r
-@ stdcall GetCurrentThemeName(wstr long wstr long wstr long)\r
-@ stdcall GetThemeAppProperties()\r
-@ stdcall GetThemeBackgroundContentRect(ptr ptr long long ptr ptr)\r
-@ stdcall GetThemeBackgroundExtent(ptr ptr long long ptr ptr)\r
-@ stdcall GetThemeBackgroundRegion(ptr ptr long long ptr ptr)\r
-@ stdcall GetThemeBool(ptr long long long ptr)\r
-@ stdcall GetThemeColor(ptr long long long ptr)\r
-@ stdcall GetThemeDocumentationProperty(wstr wstr wstr long)\r
-@ stdcall GetThemeEnumValue(ptr long long long ptr)\r
-@ stdcall GetThemeFilename(ptr long long long wstr long)\r
-@ stdcall GetThemeFont(ptr ptr long long long ptr)\r
-@ stdcall GetThemeInt(ptr long long long ptr)\r
-@ stdcall GetThemeIntList(ptr long long long ptr)\r
-@ stdcall GetThemeMargins(ptr ptr long long long ptr ptr)\r
-@ stdcall GetThemeMetric(ptr ptr long long long ptr)\r
-@ stdcall GetThemePartSize(ptr ptr long long ptr long ptr)\r
-@ stdcall GetThemePosition(ptr long long long ptr)\r
-@ stdcall GetThemePropertyOrigin(ptr long long long ptr)\r
-@ stdcall GetThemeRect(ptr long long long ptr)\r
-@ stdcall GetThemeString(ptr long long long wstr long)\r
-@ stdcall GetThemeSysBool(ptr long)\r
-@ stdcall GetThemeSysColor(ptr long)\r
-@ stdcall GetThemeSysColorBrush(ptr long)\r
-@ stdcall GetThemeSysFont(ptr long ptr)\r
-@ stdcall GetThemeSysInt(ptr long ptr)\r
-@ stdcall GetThemeSysSize(ptr long)\r
-@ stdcall GetThemeSysString(ptr long wstr long)\r
-@ stdcall GetThemeTextExtent(ptr ptr long long wstr long long ptr ptr)\r
-@ stdcall GetThemeTextMetrics(ptr ptr long long ptr)\r
-@ stdcall GetWindowTheme(ptr)\r
-@ stdcall HitTestThemeBackground(ptr long long long long ptr long long long ptr)\r
-@ stdcall IsAppThemed()\r
-@ stdcall IsThemeActive()\r
-@ stdcall IsThemeBackgroundPartiallyTransparent(ptr long long)\r
-@ stdcall IsThemeDialogTextureEnabled(ptr)\r
-@ stdcall IsThemePartDefined(ptr long long)\r
-@ stdcall OpenThemeData(ptr wstr)\r
-@ stdcall SetThemeAppProperties(long)\r
-@ stdcall SetWindowTheme(ptr wstr wstr)\r
+# Undocumented functions - Names derived from debug symbols
+1  stdcall -noname QueryThemeServices()
+2  stdcall -noname OpenThemeFile(wstr wstr wstr ptr long)
+3  stdcall -noname CloseThemeFile(ptr)
+4  stdcall -noname ApplyTheme(ptr ptr ptr)
+7  stdcall -noname GetThemeDefaults(wstr wstr long wstr long)
+8  stdcall -noname EnumThemes(wstr ptr ptr)
+9  stdcall -noname EnumThemeColors(wstr wstr long ptr)
+10 stdcall -noname EnumThemeSizes(wstr wstr long ptr)
+11 stdcall -noname ParseThemeIniFile(wstr wstr ptr ptr)
+13 stub -noname DrawNCPreview
+14 stub -noname RegisterDefaultTheme
+15 stub -noname DumpLoadedThemeToTextFile
+16 stub -noname OpenThemeDataFromFile
+17 stub -noname OpenThemeFileFromData
+18 stub -noname GetThemeSysSize96
+19 stub -noname GetThemeSysFont96
+20 stub -noname SessionAllocate
+21 stub -noname SessionFree
+22 stub -noname ThemeHooksOn
+23 stub -noname ThemeHooksOff
+24 stub -noname AreThemeHooksActive
+25 stub -noname GetCurrentChangeNumber
+26 stub -noname GetNewChangeNumber
+27 stub -noname SetGlobalTheme
+28 stub -noname GetGlobalTheme
+29 stdcall -noname CheckThemeSignature(wstr)
+30 stub -noname LoadTheme
+31 stub -noname InitUserTheme
+32 stub -noname InitUserRegistry
+33 stub -noname ReestablishServerConnection
+34 stub -noname ThemeHooksInstall
+35 stub -noname ThemeHooksRemove
+36 stub -noname RefreshThemeForTS
+43 stub -noname ClassicGetSystemMetrics
+44 stub -noname ClassicSystemParametersInfoA
+45 stub -noname ClassicSystemParametersInfoW
+46 stub -noname ClassicAdjustWindowRectEx
+48 stub -noname GetThemeParseErrorInfo
+60 stub -noname CreateThemeDataFromObjects
+61 stub -noname OpenThemeDataEx
+62 stub -noname ServerClearStockObjects
+63 stub -noname MarkSelection
+
+# Standard functions
+@ stdcall CloseThemeData(ptr)
+@ stdcall DrawThemeBackground(ptr ptr long long ptr ptr)
+@ stdcall DrawThemeBackgroundEx(ptr ptr long long ptr ptr)
+@ stdcall DrawThemeEdge(ptr ptr long long ptr long long ptr)
+@ stdcall DrawThemeIcon(ptr ptr long long ptr ptr long)
+@ stdcall DrawThemeParentBackground(ptr ptr ptr)
+@ stdcall DrawThemeText(ptr ptr long long wstr long long long ptr)
+@ stdcall EnableThemeDialogTexture(ptr long)
+@ stdcall EnableTheming(long)
+@ stdcall GetCurrentThemeName(wstr long wstr long wstr long)
+@ stdcall GetThemeAppProperties()
+@ stdcall GetThemeBackgroundContentRect(ptr ptr long long ptr ptr)
+@ stdcall GetThemeBackgroundExtent(ptr ptr long long ptr ptr)
+@ stdcall GetThemeBackgroundRegion(ptr ptr long long ptr ptr)
+@ stdcall GetThemeBool(ptr long long long ptr)
+@ stdcall GetThemeColor(ptr long long long ptr)
+@ stdcall GetThemeDocumentationProperty(wstr wstr wstr long)
+@ stdcall GetThemeEnumValue(ptr long long long ptr)
+@ stdcall GetThemeFilename(ptr long long long wstr long)
+@ stdcall GetThemeFont(ptr ptr long long long ptr)
+@ stdcall GetThemeInt(ptr long long long ptr)
+@ stdcall GetThemeIntList(ptr long long long ptr)
+@ stdcall GetThemeMargins(ptr ptr long long long ptr ptr)
+@ stdcall GetThemeMetric(ptr ptr long long long ptr)
+@ stdcall GetThemePartSize(ptr ptr long long ptr long ptr)
+@ stdcall GetThemePosition(ptr long long long ptr)
+@ stdcall GetThemePropertyOrigin(ptr long long long ptr)
+@ stdcall GetThemeRect(ptr long long long ptr)
+@ stdcall GetThemeString(ptr long long long wstr long)
+@ stdcall GetThemeSysBool(ptr long)
+@ stdcall GetThemeSysColor(ptr long)
+@ stdcall GetThemeSysColorBrush(ptr long)
+@ stdcall GetThemeSysFont(ptr long ptr)
+@ stdcall GetThemeSysInt(ptr long ptr)
+@ stdcall GetThemeSysSize(ptr long)
+@ stdcall GetThemeSysString(ptr long wstr long)
+@ stdcall GetThemeTextExtent(ptr ptr long long wstr long long ptr ptr)
+@ stdcall GetThemeTextMetrics(ptr ptr long long ptr)
+@ stdcall GetWindowTheme(ptr)
+@ stdcall HitTestThemeBackground(ptr long long long long ptr long long long ptr)
+@ stdcall IsAppThemed()
+@ stdcall IsThemeActive()
+@ stdcall IsThemeBackgroundPartiallyTransparent(ptr long long)
+@ stdcall IsThemeDialogTextureEnabled(ptr)
+@ stdcall IsThemePartDefined(ptr long long)
+@ stdcall OpenThemeData(ptr wstr)
+@ stdcall SetThemeAppProperties(long)
+@ stdcall SetWindowTheme(ptr wstr wstr)
index cfd80fb..96bb34a 100644 (file)
@@ -66,6 +66,15 @@ typedef BOOL (CALLBACK*ParseThemeIniFileProc)(DWORD dwType, LPWSTR pszParam1,
                                               LPWSTR pszParam2, LPWSTR pszParam3,
                                               DWORD dwParam, LPVOID lpData);
 
+/* Structure filled in by EnumThemeColors() and EnumeThemeSizes() with the
+ * various strings for a theme color or size. */
+typedef struct tagTHEMENAMES
+{
+    WCHAR szName[MAX_PATH+1];
+    WCHAR szDisplayName[MAX_PATH+1];
+    WCHAR szTooltip[MAX_PATH+1];
+} THEMENAMES, *PTHEMENAMES;
+
 /* Declarations for undocumented functions for use internally */
 DWORD WINAPI QueryThemeServices(void);
 HRESULT WINAPI OpenThemeFile(LPCWSTR pszThemeFileName, LPCWSTR pszColorName,
@@ -79,12 +88,19 @@ HRESULT WINAPI GetThemeDefaults(LPCWSTR pszThemeFileName, LPWSTR pszColorName,
 HRESULT WINAPI EnumThemes(LPCWSTR pszThemePath, EnumThemeProc callback,
                           LPVOID lpData);
 HRESULT WINAPI EnumThemeColors(LPWSTR pszThemeFileName, LPWSTR pszSizeName,
-                               DWORD dwColorNum, LPWSTR pszColorName);
+                               DWORD dwColorNum, PTHEMENAMES pszColorNames);
 HRESULT WINAPI EnumThemeSizes(LPWSTR pszThemeFileName, LPWSTR pszColorName,
-                              DWORD dwSizeNum, LPWSTR pszSizeName);
+                              DWORD dwSizeNum, PTHEMENAMES pszColorNames);
 HRESULT WINAPI ParseThemeIniFile(LPCWSTR pszIniFileName, LPWSTR pszUnknown,
                                  ParseThemeIniFileProc callback, LPVOID lpData);
 
 extern void UXTHEME_InitSystem(HINSTANCE hInst);
 
-#endif
+/* No alpha blending */
+#define ALPHABLEND_NONE             0
+/* "Cheap" binary alpha blending - but possibly faster */
+#define ALPHABLEND_BINARY           1
+/* Full alpha blending */
+#define ALPHABLEND_FULL             2
+
+#endif /* __WINE_UXTHEMEDLL_H */