I'm trying to understand how the SpeedButton
Glyph
property work, I find that the field declared as:
FGlyph: TObject;
While the property
as:
property Glyph: TBitmap read GetGlyph write SetGlyph stored HasCustomGlyph;
That put me in a way where I can't understand that code even if I read it line by line, when I was trying to create my own SpeedButton
that accepts .PNG
images too instead of .bmp
images only.
For the first time I was thinking to declare the property as TPicture
instead of TBitmap
.
Is there any way to create MySpeedButton with Glyph : TPicture
?
What I try is below:
TMyButton = class(TSpeedButton)
private
//
FGlyph: TPicture;
procedure SetGlyph(const Value: TPicture);
protected
//
public
//
published
//
Property Glyph : TPicture read FGlyph write SetGlyph;
end;
And the procedure:
procedure TMyButton.SetGlyph(const Value: TPicture);
begin
FGlyph := Value;
end;
I have created a similar component that is a SpeedButton which accepts a TPicture as its Glyph.
this is the unit. I hope you benefit well from it.
The first part is about how the
Glyph
property ofTSpeedButton
works, as you seem to be asking that as a part of your problem.While
TSpeedButton
'sFGlyph
field is declared as anTObject
, you will find that in code it actually contains an instance ofTButtonGlyph
. In theTSpeedButton
constructor you will find the lineFGlyph := TButtonGlyph.Create;
and the setter and getter for theGlyph
property ofTSpeedButton
look like this:So
TSpeedButton
'sGlyph
property actually accesses theGlyph
property of theTButtonGlyph
class, an internal class defined inVcl.Buttons
, which encapsulates - among other things - the actualTBitMap
with following propertySo the
TButtonGlyph
has anTBitMap
field FOriginal and the setter is implemented like this:At this point it is important how accepts .PNG is defined:
For the latter I believe the answer of Remy Lebeau is the best advice. The internal class
TButtonGylph
makes OOP approaches like inheritance with png capable class impossible as far as I see. Or even go further and do as Remy suggests in a comment: third-party component.If trade-offs are acceptable however:
Note the
FOriginal.Assign(Value);
which can already help in using PNGs, asTPNGImage
'sAssignTo
procedure knows how to assign itself to aTBitMap
. With the above known about theGlyph
property, we can simply assign a PNG with the following code:Due to differences between bitmap and PNG this might however ignore alpha channel of the PNG, but based on an answer from Andreas Rejbrand there is a partial solution for that:
Your
SetGlyph()
needs to callFGlyph.Assign(Value)
instead ofFGlyph := Value
. Be sure to createFGlyph
in the constructor and destroy it in the destructor. Then you can call draw the graphic in an overridenPaint()
whenGraphic
is not empty.