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);
* 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);
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());
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;
/***********************************************************************
* 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;
}
/***********************************************************************
*/
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
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);
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);
SelectObject(hdcSrc, oldSrc);
DeleteDC(hdcSrc);
- DeleteObject(bmpSrc);
return hr;
}
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
*
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);
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;
}
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;
}
}
}
- 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;
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;
}
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)
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.@)
*/
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);
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.@)
*/
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;
}
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);
}
#include "config.h"
#include <stdarg.h>
+#include <stdio.h>
#include "windef.h"
#include "winbase.h"
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
*
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) {
lstrcpynW(szCurrentSize, tf->pszSelectedSize, sizeof(szCurrentSize)/sizeof(szCurrentSize[0]));
}
else {
+ UXTHEME_RestoreSystemMetrics();
bThemeActive = FALSE;
szCurrentTheme[0] = '\0';
szCurrentColor[0] = '\0';
}
else
TRACE("Failed to open theme registry key\n");
+
+ UXTHEME_SaveSystemMetrics ();
+
return hr;
}
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)) {
* 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
* 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);
}
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;
* 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
* 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);
}
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;