Opened 9 years ago

Closed 8 months ago

#2609 closed defect (fixed)

wxMSW 2.6.0: Bad rendering of PNG icons with alpha channel

Reported by: wxdeveloper Owned by:
Priority: low Milestone: 3.0.1
Component: wxMSW Version: dev-latest
Keywords: wxToolBar wxImageList Common Control alpha transparency Cc: wxdeveloper, leio
Blocked By: Blocking:
Patch: yes

Description

wxToolBar tool buttons using two PNG bitmaps with
alpha channel render themselves badly when XP theme
is off (wxUSE_NO_MANIFEST = 1).
Instead of transparency they show black background
and dark grey icon when they are disabled.

wxListCtrl PNG icons with alpha channel show black
background instead of transparency when running with
no manifest turned on.

(To reproduce the problem, the attached project should
be built with wxUSE_NO_MANIFEST set to 1 in
sample.rc)

Attachments (7)

minimal.zip download (159.0 KB) - added by wxdeveloper 9 years ago.
Altered minimal sample project demonstrating the problem.
2609.patch download (28.9 KB) - added by oneeyeman 3 years ago.
Patch to minimal sample to demonstrate the problem
2609.diff download (26.4 KB) - added by vadz 3 years ago.
Minimal version of the patch
disabled-image-toolbar.png download (17.4 KB) - added by awi 9 months ago.
Results of tests.
disabled-image-list.patch download (2.0 KB) - added by awi 9 months ago.
Disable alpha channel for 'list of disabled icons'.
disabled-image-toolbar-XP.png download (15.3 KB) - added by awi 9 months ago.
Results of tests - Windows XP
image-list.patch download (4.3 KB) - added by awi 9 months ago.
Patch to image list

Download all attachments as: .zip

Change History (21)

Changed 9 years ago by wxdeveloper

Altered minimal sample project demonstrating the problem.

comment:1 Changed 3 years ago by oneeyeman

I just ran the attached sample.
Issue #2 is gone. There is no black background in the list control. However, in the list control header there is no transparency. It still shows grey background. But I don't know if it's a bug or not.

Issue #1 is still present. The result is: the button background is black but the toolbar is transparent. I tested the enabled button only, no idea about disabled one.

I can try to generate a diff to the minimal sample or I can simply attach the image OP used for testing as it simply inlined in the code.

Let me know.

Changed 3 years ago by oneeyeman

Patch to minimal sample to demonstrate the problem

comment:2 Changed 3 years ago by oneeyeman

Attached is the patch from the source code that demonstrates issue #1.

comment:3 Changed 3 years ago by vadz

  • Priority changed from normal to low

Strangely enough, I can't reproduce the problem here, even without using the manifest.

In any case this is low priority as long as it works correctly in the default build which does use the manifest.

P.S. Attaching the diff with really minimal changes to the minimal sample that actually compiles without the original sources.

Changed 3 years ago by vadz

Minimal version of the patch

comment:4 Changed 3 years ago by oneeyeman

Vadim,
Which Windows version did you use for testing?
I was on Windows XP SP2 32-bit with VS6.

comment:5 Changed 3 years ago by vadz

I tested under Win7 but with disabled visual styles. You're right though, it's not quite the same thing, I'll try to retest it under XP.

comment:6 Changed 3 years ago by oneeyeman

Can anybody who has an XP machine reproduce this behavior?
Looks like Vadim is too busy... ;-)

Changed 9 months ago by awi

Results of tests.

Changed 9 months ago by awi

Disable alpha channel for 'list of disabled icons'.

comment:7 Changed 9 months ago by awi

  • Keywords wxToolBar wxImageList Common Control alpha transparency added
  • Patch set
  • Version set to dev-latest

It seems it is possible to reproduce the issue even on Win 7 machine but whole library must be compiled with wxUSE_NO_MANIFEST set to 1 in setup.h.

The problem seems to lie in the set of features supported in different versions of Common Control library.
When this option was set to 1, no special manifest was generated, CC v5.82 was in use and the problem occurred.
When this option was set to 0, special manifest was generated, CC v6.16 was in use and everything was OK.
(Results of tests on attached screenshots.)

Apparently, Common Control library prior to ver. 6 doesn't support the list of disabled images with transparency in toolbars (with use of TB_SETDISABLEDIMAGELIST message).
It seems that it's necessary to disable alpha channel in icons on the list and to simulate transparency with bitmap mask in this case.

comment:8 follow-up: Changed 9 months ago by vadz

  • Milestone set to 3.0.1
  • Status changed from new to confirmed

Thanks for the fix! I wonder however if the problem is with TB_SETDISABLEDIMAGELIST or the image list itself, i.e. whether we shouldn't avoid using alpha for comctl32.dll < v6 in its code? I'm thinking of something like this:

better way can be found.
+    //
+    // Notice that older versions of comctl32.dll don't support alpha at all,
+    // so for them we should always use the mask and not alpha anyhow.
     AutoHBITMAP hbmpRelease;
-    if ( bitmap.HasAlpha() )
+    if ( bitmap.HasAlpha() && wxApp::GetComCtl32Version() >= 600 )
     {
         hbmp = wxDIB(bitmap.ConvertToImage(),
                      wxDIB::PixelFormat_NotPreMultiplied).Detach();
         hbmpRelease.Init(hbmp);
+
+        useMask = false;
     }
     else
 #endif // wxUSE_WXDIB && wxUSE_IMAGE
+    {
         hbmp = GetHbitmapOf(bitmap);

+        useMask = true;
+    }
+
     // Use mask only if we don't have alpha, the bitmap isn't drawn correctly
     // if we use both.
     AutoHBITMAP hbmpMask;
-    if ( !bitmap.HasAlpha() )
+    if ( useMask )
         hbmpMask.Init(GetMaskForImage(bitmap, mask));

     int index = ImageList_Add(GetHImageList(), hbmp, hbmpMask);
@@ -183,7 +193,7 @@ int wxImageList::Add(const wxBitmap& bitmap, const wxColour& maskColour)
 #if wxUSE_WXDIB && wxUSE_IMAGE
     // See the comment in overloaded Add() above.
     AutoHBITMAP hbmpRelease;
-    if ( bitmap.HasAlpha() )
+    if ( bitmap.HasAlpha() && wxApp::GetComCtl32Version() >= 600 )
     {
         hbmp = wxDIB(bitmap.ConvertToImage(),
                      wxDIB::PixelFormat_NotPreMultiplied).Detach();
@@ -224,6 +234,7 @@ bool wxImageList::Replace(int index,
                           const wxBitmap& mask)
 {
     HBITMAP hbmp;
+    bool useMask;

 #if wxUSE_WXDIB && wxUSE_IMAGE
     // See the comment in Add() above.
@@ -233,12 +244,20 @@ bool wxImageList::Replace(int index,
         hbmp = wxDIB(bitmap.ConvertToImage(),
                      wxDIB::PixelFormat_NotPreMultiplied).Detach();
         hbmpRelease.Init(hbmp);
+
+        useMask = false;
     }
     else
 #endif // wxUSE_WXDIB && wxUSE_IMAGE
+    {
         hbmp = GetHbitmapOf(bitmap);

-    AutoHBITMAP hbmpMask(GetMaskForImage(bitmap, mask));
+        useMask = true;
+    }
+
+    AutoHBITMAP hbmpMask;
+    if ( useMask )
+        hbmpMask.Init(GetMaskForImage(bitmap, mask));

     if ( !ImageList_Replace(GetHImageList(), index, hbmp, hbmpMask) )
     {

What do you think?

Changed 9 months ago by awi

Results of tests - Windows XP

Changed 9 months ago by awi

Patch to image list

comment:9 in reply to: ↑ 8 Changed 9 months ago by awi

Replying to vadz:

I did some additional tests on Win XP machine (screenshot attached) and the results are the same as for Win 7. For comctl32.dll v6.00 the icon is OK, for v5.82 it's not.

I think you are perfectly right that problem is not only with TB_SETDISABLEDIMAGELIST message but with image list itself, so your patch cures the real disease.
I would only add two (and half) things:

  1. Force to set the flag 'use mask' when image list is created (comctl32.dll < v6.00).
  2. If bitmap to be added to the list has alpha channel and comctl32.dll < v6.00 then 'physically' remove alpha channel from this bitmap before it is added to the list in order to prevent unwanted interferences between image with transparency and its mask (similar issue was encountered in #11476).

2.5. Cosmetic change in wxToolBar - when the image list for disabled icons is created then check for alpha channel to determine whether image list should use masks (if bitmap has no mask it will be created anyway).

Patch file attached.

comment:10 Changed 9 months ago by VZ

  • Resolution set to fixed
  • Status changed from confirmed to closed

(In [75785]) Fix transparency in toolbar buttons when not using comctl32.dll v6.

Old versions of comctl32.dll don't support alpha in the toolbar image list, so
use the masks only for them.

Closes #2609.

comment:11 Changed 9 months ago by vadz

  • Resolution changed from fixed to port to stable
  • Status changed from closed to portneeded

comment:12 Changed 9 months ago by VZ

(In [75794]) Compilation fix for PCH-less build.

This should fix compilation without PCH after r75785.

See #2609.

comment:13 Changed 8 months ago by VZ

(In [75923]) Compilation fix for wxUSE_IMAGE==0 wxMSW build.

Declare the variable used in any case outside of wxUSE_IMAGE-only block.

See #2609.

comment:14 Changed 8 months ago by VZ

  • Resolution changed from port to stable to fixed
  • Status changed from portneeded to closed

(In [75924]) Fix transparency in toolbar buttons when not using comctl32.dll v6.

Old versions of comctl32.dll don't support alpha in the toolbar image list, so
use the masks only for them.

This is a backport of r75785, r75794 and r75923 from trunk.

Closes #2609.

Note: See TracTickets for help on using tickets.