How to draw image with alpha channel in TSpeedButton?

I have TSpeedButton and TSpeedButton which contain various glyphs. One of them has an alpha channel, and it looks very good when it is drawn to certain parts of the user interface ... but when this glyph is drawn on TSpeedButton , it does not take the alpha channel into action.

Considering the corresponding code in TButtonGlyph.DrawButtonGlyph , it gets true for the Transparent parameter, but Transparent is not taken into account in the if FThemesEnabled code path if FThemesEnabled ; it refers only to the else section. Since themes are included in this program, does this mean that it is not possible to display an alpha mixed image in TSpeedButton ?

Is there any way around this?

EDIT: Looking at it a little closer, it seems like it takes into account transparency ... sort of. Pixels that are completely transparent do not draw at all, which is the correct behavior. But anti-aliasing (partial transparency) around the edges is drawn as completely opaque.

+5
source share
2 answers

From what I see, TSpeedButton takes your bitmap and adds it to the list of images. This is a FGlyphList in the private section of TButtonGlyph . This image list has ColorDepth of cdDeviceDependent . You will need this image list for ColorDepth cd32Bit if you want alpha transparency to be respected. So artifacts are explained here.

I'm not sure how you get around this. I think I personally subclass TButtonGlyph and connect it directly to the list of images of your choice. Then replace TButtonGlyph.DrawButtonGlyph code that is extracted from your image list. I am sure you can develop an encoding.

But there will be no easy workaround. Without significant changes to the VCL, this list of images will use cdDeviceDependent , and there is no easy way to change it. I do not see an obvious quick fix.

Actually, I would do to use TButton , but that's just me.


Regarding the Transparent property of the speed button, the documentation says:

Indicates whether the background of the button is transparent.

Use Transparent to indicate whether the background of the button is transparent.

This property only works if the Flat property of TSpeedButton is set to True.

When Windows themes are enabled, the Transparent property cannot make the background button transparent.

That is, the property affects the background of the button, for flat buttons, when it is unsealed, and has nothing to do with glyph drawing.

+4
source

In the interest of full disclosure: I ran into a similar problem and used this Q & A to install my initial solution. Since I needed a quick fix for my application and compiler (I use C ++ Builder 2009), I decided to β€œhack” the private members of VCL and set Glyphlist ColorDepth to cd32Bit until I had time to work on something more permanent. This hack worked with a few changes, but was far from ideal, for all obvious reasons, but also with functionality, there were problems that should be considered.

However, by doing this, I experimented further and finally came below, a working solution, without any dirty tricks. Not being familiar with the internal development of VCL and rather β€œit is not possible as it is,” feedback from people who are much deeper in VCL, I’m a little unsure of what I’m missing right now !? Because below solution works for me. Confirmed on XP, XP-High-contrast, W7 and W10. The characters do not look good on W2K, but then this is true for the main menu and pop-up icons, so it is.

I am C ++ code, but using the same basic VCL, so I will post my C ++ solution here as an answer to a Delphi question. I hope that everything is in order, in the interests of proposing a path to a solution, and not keeping it to ourselves. Guru Delphi can also convert and publish as an answer if I don't miss something and my decision is not what I needed all the time.

Since I started with the β€œhack” approach, I first subclassed TSpeedButton and put the code in the MyTSpeedButton function, but this is not necessary to complete this work. However, this is the code I'm sending:

heading

 class MyVCLTSpeedButton : public TSpeedButton { public: __fastcall MyVCLTSpeedButton(Classes::TComponent* AOwner) ; void __fastcall AddGlyphWithAlphaChannel(Imglist::TCustomImageList* ImageList, int UpIndex, int DisabledIndex = -1, int ClickedIndex = -1, int DownIndex = -1) ; }; 

caste

 void __fastcall MyVCLTSpeedButton::AddGlyphWithAlphaChannel(Imglist::TCustomImageList* ImageList, int UpIndex, int DisabledIndex, int ClickedIndex, int DownIndex) { Glyph->Assign(NULL) ; // Clear the current bitmap NumGlyphs = (DisabledIndex > -1)?((ClickedIndex > -1)?((DownIndex > -1)?(4):(3)):(2)):(1) ; Graphics::TBitmap *BitMap = new Graphics::TBitmap ; //BitMap->AlphaFormat = afDefined ; // Don't Change AlphaFormat, it will negatively affect rendering ! BitMap->PixelFormat = pf32bit ; // Doesn't seem to be that important BitMap->Height = ImageList->Height ; BitMap->Width = (ImageList->Width * NumGlyphs) ; BitMap->Canvas->Brush->Color = Parent->Brush->Color ; BitMap->Canvas->Brush->Style = bsSolid ; BitMap->Canvas->FillRect(BitMap->Canvas->ClipRect) ; TIcon *Icon = new TIcon() ; for (int x = 0 ; x < NumGlyphs ; x++) { ImageList->GetIcon((x == 0)?(UpIndex):((x == 1)?(DisabledIndex):((x == 2)?(ClickedIndex):(DownIndex))), Icon) ; BitMap->Canvas->Draw((ImageList->Width * x), 0, Icon) ; } Glyph->Assign(BitMap) ; delete Icon ; delete BitMap ; } 
0
source

Source: https://habr.com/ru/post/1202286/


All Articles