Paint a complete TTreeView on a canvas (Views: 28)
Problem/Question/Abstract: How to paint a complete TTreeView on a canvas Answer: I recently implemented a procedure to paint a TTreeView component to a canvas, including the images, state images and so on, and not only the visible nodes, but also those that do not fit in the client area. unit TreePaint; interface uses Windows, Graphics, ComCtrls; procedure TreeViewPaintTo(ATreeView: TTreeView; FullExpand: Boolean; ACanvas: TCanvas; X, Y: Integer); implementation procedure TreeViewPaintTo(ATreeView: TTreeView; FullExpand: Boolean; ACanvas: TCanvas; X, Y: Integer); var OffsetX, OffsetY: Integer; procedure DrawButton(X, Y: Integer; Expanded: Boolean); var R: TRect; begin ACanvas.Pen.Color := clGray; ACanvas.Pen.Style := psSolid; ACanvas.Rectangle(X - 5, Y - 5, X + 4, Y + 4); ACanvas.Pixels[X + 1, Y - 1] := clBlack; ACanvas.Pixels[X, Y - 1] := clBlack; ACanvas.Pixels[X - 1, Y - 1] := clBlack; ACanvas.Pixels[X - 2, Y - 1] := clBlack; ACanvas.Pixels[X - 3, Y - 1] := clBlack; if (not Expanded) then begin ACanvas.Pixels[X - 1, Y + 1] := clBlack; ACanvas.Pixels[X - 1, Y] := clBlack; ACanvas.Pixels[X - 1, Y - 1] := clBlack; ACanvas.Pixels[X - 1, Y - 2] := clBlack; ACanvas.Pixels[X - 1, Y - 3] := clBlack; end; end; procedure DrawHorizLine(X, Y: Integer; HasButton: Boolean); begin if (HasButton) then X := X + 5; ACanvas.Pixels[X, Y] := clGray; ACanvas.Pixels[X + 2, Y] := clGray; ACanvas.Pixels[X + 4, Y] := clGray; end; procedure DrawVertLine(X, Y0, Y1: Integer; HasButton: Boolean); begin if (HasButton) then Y0 := Y0 + 5; while (Y0 <= Y1) do begin ACanvas.Pixels[X, Y0] := clGray; inc(Y0, 2); end; end; procedure TreeNodePaintTo(ATreeNode: TTreeNode; ACanvas: TCanvas); var FirstNode: Boolean; CurNode: TTreeNode; NewX, NewY, CurX, CurY, StateY, ImageY: Integer; begin CurNode := ATreeNode; FirstNode := True; while (CurNode <> nil) do begin if (not (CurNode.IsVisible or FullExpand)) then Exit; {Compute Start X and Y} NewX := X + (CurNode.Level * OffsetX); NewY := Y + (OffsetY div 2); {Line to sibling node} if (ATreeView.ShowLines) then begin if (not FirstNode) then begin if (ATreeView.ShowRoot or (CurNode.Level > 0)) then DrawVertLine(NewX - 1, CurY - (OffsetY div 2) + 1, NewY, True); end else begin FirstNode := False; {Line to parent node} if (CurNode.Parent <> nil) then DrawVertLine(NewX - 1, Y - (OffsetY div 2) + 1, NewY, True) end; end; {Update Sibling offsets} CurX := NewX; CurY := NewY; if (ATreeView.ShowRoot or (CurNode.Level > 0)) then begin if (ATreeView.ShowButtons) then begin {Draw the button} if (CurNode.HasChildren) then begin DrawButton(NewX, NewY, FullExpand or CurNode.Expanded); CurY := CurY + 9; end; if (ATreeView.ShowLines) then DrawHorizLine(NewX, NewY, CurNode.HasChildren); end else if (ATreeView.ShowLines) then DrawHorizLine(NewX, NewY, False); end; {Update X Offset} NewX := NewX + 9; {State Image} if (Assigned(ATreeView.StateImages)) then begin {Draw the State Image} StateY := Y + ((OffsetY - ATreeView.StateImages.Height) div 2); ATreeView.StateImages.Draw(ACanvas, NewX, StateY, CurNode.StateIndex); {Update X Offset} NewX := NewX + ATreeView.StateImages.Width; end; {Image} if (Assigned(ATreeView.Images)) then begin {Draw the Image} ImageY := Y + ((OffsetY - ATreeView.Images.Height) div 2); ATreeView.Images.Draw(ACanvas, NewX, ImageY, CurNode.ImageIndex); {Update X Offset} NewX := NewX + ATreeView.Images.Width; end; ACanvas.TextOut(NewX, Y, CurNode.Text); {Update Y Offset} Y := Y + OffsetY; {Paint Child Nodes} if (CurNode.GetFirstChild <> nil) then TreeNodePaintTo(CurNode.GetFirstChild, ACanvas); {Paint sibling nodes} CurNode := CurNode.GetNextSibling; end; end; begin {Compute Offsets} OffsetX := 19; OffsetY := 5 * ACanvas.TextHeight('|') div 4; if (Assigned(ATreeView.StateImages)) and (ATreeView.StateImages.Height > OffsetY) then OffsetY := ATreeView.StateImages.Height; if (Assigned(ATreeView.Images)) and (ATreeView.Images.Height > OffsetY) then OffsetY := ATreeView.Images.Height; if (ATreeView.ShowRoot) then X := X + 10; TreeNodePaintTo(ATreeView.Items.GetFirstNode, ACanvas); end; end. |