Using either TTreeView.OnAdvancedCustomDrawItem or TTreeView.CustomDrawItem, how does one completely draw an tree view item? There is no sample code on the docwiki for the Advanced custom draw item.
The Delphi documentation wiki has a confusing sample that references code that does not exist in the sample, and does not compile. I take it that the problem is split into three separate painting issues:
- Get the theme element for the Windows tree view node and draw it.
- Get any image that exists in the node and paint it.
- Draw the text for the node.
Finally, one should set DefaultDraw := false
so that the control doesn't do the default painting for the node.
It seems to me that such a basic thing should exist as a real working sample somewhere, but the closest I have found, is the documentation wiki which just says "See this other thing" and provides no link to the rest of the code.
The non-working sample with rather too much hand-waving and incomplete code, references some things that are not defined in this demo, but were obviously cut and pasted from a working sample. Some of the changes one would make are obvious (like define your own way to get the colors for the brush, and your own way to decide what font the node should be), and some are not, like how to implement DrawButton
:
procedure TCustomDrawForm.TVCustomDrawItem(Sender: TCustomTreeView; Node: TTreeNode;
State: TCustomDrawState; var DefaultDraw: Boolean);
var
NodeRect: TRect;
begin
with TV.Canvas do
begin
{
If DefaultDraw it is true, any of the node's font
properties can be changed. Note also that when
DefaultDraw = True, Windows draws the buttons and
ignores our font background colors, using instead the
TreeView's Color property.
}
if cdsSelected in State then
begin
Font.Assign(SelectedFontDialog.Font);
Brush.Color := SelBkgColorDialog.Color;
end;
DefaultDraw := False; // FDefaultDrawItem;
{
DefaultDraw = False means you have to handle all the
item drawing yourself, including the buttons, lines,
images, and text.
}
if not DefaultDraw then
begin
//draw the selection rect.
if cdsSelected in State then
begin
NodeRect := Node.DisplayRect(True);
FillRect(NodeRect);
end;
NodeRect := Node.DisplayRect(False);
if None1.Checked then
//no bitmap, so paint in the background color.
begin
Brush.Color := BkgColorDialog.Color;
Brush.Style := FBrushStyle;
FillRect(NodeRect)
end
else
//don't paint over the background bitmap.
Brush.Style := bsClear;
NodeRect.Left := NodeRect.Left + (Node.Level * TV.Indent);
// NodeRect.Left now represents the left-most portion
// of the expand button
DrawButton(NodeRect, Node); // See the CustomDraw demo
NodeRect.Left := NodeRect.Left + TV.Indent + FButtonSize;
//NodeRect.Left is now the leftmost portion of the image.
DrawImage(NodeRect, Node.ImageIndex); // See the CustomDraw demo
NodeRect.Left := NodeRect.Left + ImageList.Width;
//Now we are finally in a position to draw the text.
TextOut(NodeRect.Left, NodeRect.Top, Node.Text);
end;
end;
end;