Don't know if there are few responses because the topic is not of interest or because most are thinking: not possible.
As demo i add a small gif sample for to show what i ssucceeded to try out because i found it to be quite nice.
The chanllenge is only, why such a big overhead described, approx. 300 lines of code cloning in the app (for to paint lines, expand sign etc., which already does exist), plus the need for to include themes.pas, only for to change a full line backcolor?
I thought about further and had an idea.
A solution could be a simple one liner within
treeview.inc, DoPaintNode.
The idea is: let me (the app) draw the line backcolor and node text (both easy) and else do your DefaultDraw .... but without painting the line background.
That means: please let me draw the item background, without either overwriting it afterwards (DefaultDraw true), or (DefaultDraw false:) force me to do a lot of things redundantly.
The idea simply is: please skip the background draw optionally by demand for certain situations, the app wants to do that itself and not been overridden by the DefaultDraw.
This is the one liner (a simple if). I tried it out and it worked fine:
// draw background
if not FSkipDrawLineBackground then // <=== added line. requires def and init of the public variable within comctrls.pp though
DrawBackground(NodeSelected, NodeRect);
In my use cases, i would set this veriable to true just if needed and now simply spend some very few code lines for background and node text, that's all.
One could care about the line backcolor and text paint, but not to struggle with lines, icon, expand sign.
Example (for highlight line at "Selected", at treeview focused or unfocused), the AdvancedCustomDrawItem could look like as:
procedure TForm1.TreeView1AdvancedCustomDrawItem(Sender: TCustomTreeView;
Node: TTreeNode; State: TCustomDrawState; Stage: TCustomDrawStage;
var PaintImages, DefaultDraw: Boolean);
var RFull, RText: Trect;
begin
DefaultDraw := True;
Sender.FSkipDrawLineBackground := False;
if cdsSelected In State then begin
Sender.FSkipDrawLineBackground := True;
if stage = cdPrePaint then begin
Sender.Canvas.Brush.Color := $00FFE8CC;
RFull := Node.DisplayRect(false);
Sender.Canvas.FillRect(RFull);
exit;
end;
DefaultDraw := False;
with Sender.Canvas do begin
RText := Node.DisplayRect(True);
Sender.Canvas.Brush.Color := $00FFE8CC;
Sender.Canvas.FillRect(RText);
inc(RText.Top, 2);
inc(RText.Left, 4);
inc(RText.Right, 4);
DrawText(Handle, PChar(Node.Text), -1, RText, DT_LEFT or DT_VCENTER);
end;
end;
end;
Test project attached )which does assume the change mentioned). It shows a full line background (just as with RowSelect, but without graying it at focus change).
For he "highlight line at mouse over" the principle is juse the same, with a bit more logic around (--> not covered in the test project).
So this does allow much more flexibility for certain vertain customization.
What do you think? Would it make sense to provide this possibility?
(With an additional var, alternatives are possible. But i think this one is the simplest).