0
votes

I'm currently working with a component called TdsTaskBar, which intends to work like the TaskBar in windows, which means all opened windows (but now inside my application) are listed as buttons on the bottom of my application-window. This buttons are TSpeedButtons. Now I've changed the icons of my own windows, this icons get always displayed via the glyph of the SpeedButtons. The problem is, that the transparency isn't working.

I'm aware of the Transparency Color defined by the lower left corner pixel, but that's not my problem. The problem is, that transparent areas of the Glyphs show "random" image artifacts instead of the button-background, when changing the active window and then hovering over the buttons. This changes the background to the icon of the now active window, but with some distortion.

First window opened Second window opened, hovered over the button

I have NO clue how this artifacts get there, but I'm sure that it doesn't come from the TdsTaskBar- / TdsTaskButton-Component, because I examined all the paint-relevant procedures.

Does someone have an idea how to solve this problem? I already thought about drawing the background myself, but therefore I'd need to know the actual button color(s) behind this Glyph, and that's another thing where I'm not sure about how to figure it out.


Here the code snippet for assigning the glyph, the drawing is handled by standard Vcl SpeedButton Code:

procedure TTaskBarButton.AssignGlyphIcon;
var
  GlyphIcon: TIcon;
  b: TBitmap;
begin
  if TForm(owner).Icon.Empty then
    GlyphIcon := Application.Icon
  else
    GlyphIcon := TForm(owner).Icon;

  b := TBitmap.create;
  try
    b.Width := GlyphIcon.Width;
    b.Height := GlyphIcon.Height;
    b.Canvas.Brush.Color := b.TransparentColor;    // This two lines were added by me
    b.Canvas.FillRect(b.ClipRect);         // so that the background of my "helper" bitmap is transparent, too
    b.Canvas.Draw(0,0, GlyphIcon);
    Glyph.Width := 16;
    Glyph.Height := 16;
    Glyph.Canvas.StretchDraw(Rect(0, 0, 16, 16), b);
  finally
    b.free;
  end;
end;
2
Seems to be a defect in the component to me, ask the designer?whosrdaddy
I have the full sources of the component, and it isn't that much code, just one short Unit. The drawing of the Glyph is simple and straightforward, I'm really sure the error doesn't lie in there. I'll edit the question and add the code of the Glyph drawing.Florian Koch
I cannot see where you clear the background of Glyph. I also don't really understand why you need b. Finally, it looks like you are using images with alpha transparency. If so, why use TransparentColor?David Heffernan
@DavidHeffernan I can also do the same "clear" I do in my bitmap in the glyph, but this doesn't change the outcome... The bitmap is used in case the application Icon isn't 16x16 pixel, so I can use the stretchdraw. I didn't invent this code, but I also didn't cahnge it because it seemed legit to me.Florian Koch
@SirRufo This is the better solution, you are right, but this doesn't change anything regarding the transparencyFlorian Koch

2 Answers

2
votes

You have to erase the Glyph background.

Here is a sample code, that should do the job

procedure TTaskBarButton.AssignGlyphIcon;
var
  b: TBitmap;
  r: TRect;
begin
  b := TBitmap.create;
  try
    if TForm( Owner ).Icon.Empty then
      b.Assign( Application.Icon )
    else
      b.Assign( TForm(Owner).Icon );

    r := TRect.Create( 0, 0, 16, 16 );
    Glyph.Width := r.Width;
    Glyph.Height := r.Height;
    // clear the background
    Glyph.Canvas.Brush.Color := Glyph.TransparentColor;
    Glyph.Canvas.FillRect( r );
    // draw the icon
    Glyph.Canvas.StretchDraw( r, b );
  finally
    b.free;
  end;
end;
0
votes

Found the solution: The TdsTaskBar (it's a TCustomPanel) has DoubleBuffered default set to false. The buttons inherit this setting. Changing this to true solves the problem.

So its seems like DoubleBuffering influences the functionality of Transparency on Buttons.