2005. március 9., szerda
Paint a complete TTreeView on a canvas
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.
Feliratkozás:
Megjegyzések küldése (Atom)
Nincsenek megjegyzések:
Megjegyzés küldése