From dbd22a81e4879bddd74592b7d0a8155fddfc1b72 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 11 Nov 2014 01:02:02 +0000 Subject: [PATCH] Improve drawing of monochrome bitmaps with masks in wxMSW. This is a compromise solution between r78040, which handled monochrome bitmaps correctly, but broke drawing bitmaps without using their mask, and r78054 which simply reverted it: this version preserves the old behaviour when not using the mask, but draws at least the shape (if not the colour) correctly for the monochrome bitmaps. Notice that this also reverts r78039 which is not needed any more without r78040. Closes #16512. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@78123 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- src/msw/bitmap.cpp | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/msw/bitmap.cpp b/src/msw/bitmap.cpp index f724ee7001..f5fe48e148 100644 --- a/src/msw/bitmap.cpp +++ b/src/msw/bitmap.cpp @@ -55,6 +55,9 @@ #define CLR_INVALID ((COLORREF)-1) #endif // no CLR_INVALID +// ROP which doesn't have standard name +#define DSTERASE 0x00220326 // dest = (NOT src) AND dest + // ---------------------------------------------------------------------------- // wxBitmapRefData // ---------------------------------------------------------------------------- @@ -513,7 +516,6 @@ bool wxBitmap::CopyFromIconOrCursor(const wxGDIImage& icon, // AND mask: 0 <= y <= h-1 // XOR mask: h <= y <= 2*h-1 // First we need to extract and store XOR mask from this bitmap. - // AND mask will be extracted later at creation of inverted mask. HBITMAP hbmp = ::CreateBitmap(w, h, 1, wxDisplayDepth(), NULL); if ( !hbmp ) { @@ -531,6 +533,18 @@ bool wxBitmap::CopyFromIconOrCursor(const wxGDIImage& icon, { wxLogLastError(wxT("wxBitmap::CopyFromIconOrCursor - BitBlt")); } + // Prepare the AND mask to be compatible with wxBitmap mask + // by seting its bits to 0 wherever XOR mask (image) bits are set to 1. + // This is done in-place by applying the following ROP: + // dest = dest AND (NOT src) where dest=AND mask, src=XOR mask + // + // AND mask will be extracted later at creation of inverted mask. + if ( !::BitBlt((HDC)dcSrc, 0, 0, w, h, + (HDC)dcSrc, 0, h, + DSTERASE) ) + { + wxLogLastError(wxT("wxBitmap::CopyFromIconOrCursor - BitBlt")); + } } refData->m_width = w; refData->m_height = h; @@ -1908,6 +1922,21 @@ HICON wxBitmapToIconOrCursor(const wxBitmap& bmp, iconInfo.hbmMask = hbmpMask; iconInfo.hbmColor = GetHbitmapOf(bmp); + // black out the transparent area to preserve background colour, because + // Windows blits the original bitmap using SRCINVERT (XOR) after applying + // the mask to the dest rect. + { + MemoryHDC dcSrc, dcDst; + SelectInHDC selectMask(dcSrc, (HBITMAP)mask->GetMaskBitmap()), + selectBitmap(dcDst, iconInfo.hbmColor); + + if ( !::BitBlt(dcDst, 0, 0, bmp.GetWidth(), bmp.GetHeight(), + dcSrc, 0, 0, SRCAND) ) + { + wxLogLastError(wxT("BitBlt")); + } + } + HICON hicon = ::CreateIconIndirect(&iconInfo); if ( !bmp.GetMask() && !bmp.HasAlpha() )