1
votes

I'm need to draw some graphics as node image. Like it draws images from ImageList in OnGetImageIndex event, but from the single source like TIcon, TImage, TBitmap.

In my situation all nodes have it own icons and places in UserData record.

How I can draw theese icons to nodes?

I found this code here, and tried to adept it for my situation:

procedure TForm10.Button1Click(Sender: TObject);
var
  Node: PVirtualNode;
begin
  VirtualStringTree1.AddChild(nil);
  Node := VirtualStringTree1.AddChild(nil);
  VirtualStringTree1.AddChild(Node);
  Node := VirtualStringTree1.AddChild(Node);
  VirtualStringTree1.AddChild(Node);
  VirtualStringTree1.AddChild(Node);
  VirtualStringTree1.AddChild(Node);
end;

procedure TForm10.VirtualStringTree1AfterItemPaint(Sender: TBaseVirtualTree;
  TargetCanvas: TCanvas; Node: PVirtualNode; ItemRect: TRect);
var
  rImage: TRect;
  OffsetLeft: Integer;
  Icon: TIcon;
begin
  rImage := ItemRect;
  Icon := TIcon.Create;
  Icon.LoadFromFile('TestIcon_16.ico');
  with TVirtualStringTree(Sender) do
  begin
    if (toShowRoot in TreeOptions.PaintOptions) then
      OffsetLeft := Indent * (GetNodeLevel(Node) + 1)
    else
      OffsetLeft := Indent * GetNodeLevel(Node);

    Inc(rImage.Left, Margin + OffsetLeft);
    Inc(rImage.Top, (NodeHeight[Node] - Icon.Height) div 2);
    rImage.Right := rImage.Left + Icon.Width;
    rImage.Bottom := rImage.Top + Icon.Height;
  end;
  DrawIcon(TargetCanvas.Handle, rImage.Left, rImage.Top, Icon.Handle);
end;

After button click, I see that: enter image description here

Why that's happens? Icon size 100% - 16 x 16 px.

Where I can solve problem with drawning of text?

What I do wrong?

1
Why it happens ? Because the tree doesn't know that you're doing that and doesn't indent node texts to make a space for your images. - TLama
How to notify it? Or exists any other idea to do this? - AlexLL
Since I don't have any expirience using this component I'm just guesing. But shouldn't you rather use OnBeforeItemPaint event instead. I asume that by using that event you might get a chance to controll the position of text so that it isn't drawn at the same place as your incons are. If nohing else you might be able to change the text by ading several empty spaces to it so it moves toward right. Doing this in OnAfterItemPaint event won't work becouse the text has already been painted at the time when event fires. - SilverWarior
Well, first of all you'll need to tell the tree to make some space. That's what you can do by increasing Extent parameter of the OnMeasureTextWidth event method. And then paint the text by yourself in the OnDrawText event method. But much better you'll go with default approach using image list. You can store those images into an image list and to each node store just index to that image list, don't you ? - TLama
You see a 32x32 icon for sure. it happens b/c you load 16x16 icon and draw it with DrawIcon which stretches it. you could use DrawIconEx or simply TargetCanvas.Draw(x, y, Icon). in any case, you leaking memory of the TIcon, and I really don't see why you don't want to use an ImageList with OnGetImageIndex which is really the right way to go?... - kobik

1 Answers

0
votes

Unfortunately VT relies on image lists not allowing using separate images. In the same time, image lists are invconvenient as long as item insert and deletion is concerned. So as a workaround option you could create an image list for each image and return it to VT via OnGetImageEx event handler.

Alternatively, you can create one dummy image list with one empty and transparent image so that VT would know what dimensions the image has and paint your own custom images in AfterPaint.