From: Mark Harmstone Subject: [PATCH] uxtheme: Support images in GetThemeBackgroundRegion. (try 2) Message-Id: <54EF9F64.9070200@burntcomma.com> Date: Thu, 26 Feb 2015 22:34:12 +0000 Resubmission using a DIB instead of a DDB. --- dlls/uxtheme/draw.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 110 insertions(+), 2 deletions(-) diff --git a/dlls/uxtheme/draw.c b/dlls/uxtheme/draw.c index 1e15d3b..acb6d28 100644 --- a/dlls/uxtheme/draw.c +++ b/dlls/uxtheme/draw.c @@ -1763,6 +1763,115 @@ HRESULT WINAPI GetThemeBackgroundExtent(HTHEME hTheme, HDC hdc, int iPartId, return S_OK; } +static HRESULT create_image_bg_region(HTHEME theme, int part, int state, const RECT *rect, HRGN *rgn) +{ + RECT r; + HDC dc; + HBITMAP bmp; + HRGN hrgn, rgntemp; + BOOL istrans; + COLORREF transcolour; + HBRUSH transbrush; + unsigned int x, y; + BITMAPINFO bitmapinfo; + unsigned char *bits, *ptr; + + r = *rect; + OffsetRect(&r, -r.left, -r.top); + + hrgn = CreateRectRgn(r.left, r.top, r.right, r.bottom); + + if (FAILED(GetThemeBool(theme, part, state, TMT_TRANSPARENT, &istrans)) || !istrans) { + OffsetRgn(hrgn, rect->left, rect->top); + *rgn = hrgn; + return S_OK; + } + + if (FAILED(GetThemeColor(theme, part, state, TMT_TRANSPARENTCOLOR, &transcolour))) + transcolour = RGB(255, 0, 255); /* defaults to magenta */ + + dc = CreateCompatibleDC(NULL); + if (!dc) { + WARN("CreateCompatibleDC failed\n"); + DeleteObject(hrgn); + return E_FAIL; + } + + bitmapinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bitmapinfo.bmiHeader.biWidth = r.right - r.left; + bitmapinfo.bmiHeader.biHeight = -(r.bottom - r.top); + bitmapinfo.bmiHeader.biPlanes = 1; + bitmapinfo.bmiHeader.biBitCount = 32; + bitmapinfo.bmiHeader.biCompression = BI_RGB; + bitmapinfo.bmiHeader.biSizeImage = bitmapinfo.bmiHeader.biWidth * bitmapinfo.bmiHeader.biHeight * 4; + bitmapinfo.bmiHeader.biXPelsPerMeter = 0; + bitmapinfo.bmiHeader.biYPelsPerMeter = 0; + bitmapinfo.bmiHeader.biClrUsed = 0; + bitmapinfo.bmiHeader.biClrImportant = 0; + + bmp = CreateDIBSection(dc, &bitmapinfo, DIB_RGB_COLORS, (void**)&bits, NULL, 0); + if (!bmp) { + WARN("CreateDIBSection failed\n"); + DeleteDC(dc); + DeleteObject(hrgn); + return E_FAIL; + } + + SelectObject(dc, bmp); + + transbrush = CreateSolidBrush(transcolour); + FillRect(dc, &r, transbrush); + DeleteObject(transbrush); + + if (FAILED(DrawThemeBackground(theme, dc, part, state, &r, NULL))) { + WARN("DrawThemeBackground failed\n"); + DeleteObject(bmp); + DeleteDC(dc); + DeleteObject(hrgn); + return E_FAIL; + } + + /* loop through the image looking for transparent pixels, + * grouping together horizontal runs into one rect */ + ptr = bits; + for (y = 0; y < r.bottom; y++) { + BOOL trans = FALSE; + int transstart; + + for (x = 0; x < r.right; x++) { + COLORREF colour = ptr[2] << 16 | ptr[1] << 8 | ptr[0]; + ptr += 4; + + if (colour == transcolour) { + if (!trans) { + transstart = x; + trans = TRUE; + } + } else if (trans) { + rgntemp = CreateRectRgn(transstart, y, x, y+1); + CombineRgn(hrgn, hrgn, rgntemp, RGN_DIFF); + DeleteObject(rgntemp); + trans = FALSE; + } + } + + if (trans) { + rgntemp = CreateRectRgn(transstart, y, r.right, y+1); + CombineRgn(hrgn, hrgn, rgntemp, RGN_DIFF); + DeleteObject(rgntemp); + } + } + + OffsetRgn(hrgn, rect->left, rect->top); + *rgn = hrgn; + + DeleteObject(bmp); + + DeleteDC(dc); + + return S_OK; +} + /*********************************************************************** * GetThemeBackgroundRegion (UXTHEME.@) * @@ -1784,8 +1893,7 @@ HRESULT WINAPI GetThemeBackgroundRegion(HTHEME hTheme, HDC hdc, int iPartId, GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_BGTYPE, &bgtype); if(bgtype == BT_IMAGEFILE) { - FIXME("Images not handled yet\n"); - hr = ERROR_CALL_NOT_IMPLEMENTED; + hr = create_image_bg_region(hTheme, iPartId, iStateId, pRect, pRegion); } else if(bgtype == BT_BORDERFILL) { *pRegion = CreateRectRgn(pRect->left, pRect->top, pRect->right, pRect->bottom);