Reputation:
I want use a Win32 TreeView control with the feature to resort the items, like it is possible inside of Windows Explorer's Favorites / Quick Access:
I didn't find an option to enable the divider between two nodes, so I think I have to draw it by myself.
To do this, I think I have to use the NM_CUSTOMDRAW
notification with the CDIS_DROPHILITED
item state. But I can't catch this. Why?
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
Unit2, Vcl.ComCtrls;
type
TForm1 = class(TForm)
TreeView1: TTreeView;
procedure TreeView1AdvancedCustomDrawItem(Sender: TCustomTreeView;
Node: TTreeNode; State: TCustomDrawState; Stage: TCustomDrawStage;
var PaintImages, DefaultDraw: Boolean);
procedure TreeView1Changing(Sender: TObject; Node: TTreeNode;
var AllowChange: Boolean);
procedure TreeView1DragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
private
procedure WMNotify(var Msg: TMessage); message WM_NOTIFY;
end;
var
Form1: TForm1;
implementation
uses
CommCtrl;
{$R *.dfm}
procedure TForm1.TreeView1AdvancedCustomDrawItem(Sender: TCustomTreeView;
Node: TTreeNode; State: TCustomDrawState; Stage: TCustomDrawStage;
var PaintImages, DefaultDraw: Boolean);
begin
if (cdsDropHilited in State) then
Write;
end;
procedure TForm1.TreeView1Changing(Sender: TObject; Node: TTreeNode;
var AllowChange: Boolean);
begin
AllowChange := Node <> TreeView1.Items[1];
end;
procedure TForm1.TreeView1DragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
begin
Accept := True;
GetComCtlVersion();
end;
procedure TForm1.WMNotify(var Msg: TMessage);
begin
case (PNMHdr(Msg.LParam)^.code) of
NM_CUSTOMDRAW:
if (PNMTVCustomDraw(Msg.LParam)^.nmcd.uItemState and CDIS_NEARHOT <> 0) then
Write;
end;
inherited;
end;
end.
Neither TreeView1AdvancedCustomDrawItem()
nor WMNotify()
reach the Write
statement.
Any suggestions? How can I draw the node dividers while implementing a drag & drop feature?
I'm using Windows 7.
Upvotes: 1
Views: 1567
Reputation:
TreeView_SetInsertMark
draws the divider like shown in the question.
Upvotes: 1
Reputation: 596287
If you look closely at how Windows Explorer draws its tree nodes, you will see that the divider you are interested in is only drawn when the mouse is over the top or lower edge of a node that is being dragged onto. Look at the positioning of the divider in relation to the target node's highlight selection when the mouse is not over its top/lower edge. They overlap.
You can accomplish the same thing in the TTreeView.OnAdvancedCustomDraw(Item)
events. Check if the TreeView's DropTarget
node (the node that will be dropped onto when the user releases the mouse) is the node currently being drawn, and if so then:
retrieve the current mouse position in client coordinates using TreeView.ScreenToClient(Mouse.CursorPos)
.
retrieve the DisplayRect
of the DropTarget
node.
check if the mouse coordinates are currently within the top or lower few pixels of that rectangle.
if so, draw your divider at those coordinates as needed.
Upvotes: 3