delphirules
delphirules

Reputation: 7448

How to draw image from TImage into TListbox?

I'm trying to create a listbox with images. The images will be fetched from a TImage component ; i don't want to use a TImageList because TImage can handle a lot of image types (png, gif, jpg) and i don't have to convert it to populate the Imagelist.

So i've set my listbox style to lbOwnerDrawVariable and i'm trying to paint the image from TImage into the listbox. I've set Image1 width and height to 50 because this is the size i want the images to have on the listbox.

Here is my code :

procedure TForm2.listbox1DrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState);
var
  CenterText: Integer;
begin
  listbox1.Canvas.FillRect(Rect);
  listbox1.Canvas.draw(rect.Left+4,rect.Top+4,image1.Picture.graphic);
  CenterText := (Rect.Bottom - Rect.top - listbox1.Canvas.TextHeight(text)) div 2;
  listbox1.Canvas.TextOut(Rect.left + 58, Rect.top + CenterText, listbox1.Items.Strings[index]);
end;

But instead of putting the image in each listbox item, it's drawing a lot of images inside thel listbox itself, with its original size instead of 50... what's wrong with my code ?

enter image description here

Upvotes: 2

Views: 1184

Answers (1)

Andreas Rejbrand
Andreas Rejbrand

Reputation: 109158

Image1.Width and Image1.Height are the dimensions of the TImage control. They have nothing to do with the dimensions of the Image1.Picture.

You need to stretch-draw the image or pre-scale it.

Just a very quick and dirty example:

procedure TForm1.ListBox1DrawItem(Control: TWinControl; Index: Integer;
  Rect: TRect; State: TOwnerDrawState);
begin

  if Control <> ListBox1 then
    Exit;

  if Index = -1 then
    Exit;

  var C := ListBox1.Canvas;

  C.Brush.Color := clWindow;
  C.Font.Color := clWindowText;
  C.FillRect(Rect);

  var R := Rect;
  var S := ListBox1.Items[Index];

  var G := Image1.Picture.Graphic;

  var scale := 1.0;

  if (G.Width > 0) and (G.Height > 0) then
  begin

    var xscale := R.Width / G.Width;
    var yscale := R.Height / G.Height;
    scale := Min(xscale, yscale);

    R.Width := Round(G.Width * scale);
    R.Height := Round(G.Height * scale);

    C.StretchDraw(R, G);

  end;

  R := Rect;
  R.Left := R.Left + Round(G.Width * scale) + C.TextWidth('0');
  C.TextRect(R, S, [tfSingleLine, tfVerticalCenter, tfEndEllipsis]);

end;

Screenshot of a form with a TImage and an owner-drawn list box using the TImage's graphic as an icon for each item.

Upvotes: 5

Related Questions