Answer:
unit TreeDragHelp;
interface
// TreeView control DragDrop Operation helper functions
// Author : bwsunv@163.com
// Date : 2003-05-04
// Features:
// 1. expand/collaps automatically
// 2. move with children nodes
// 3. disable drop to child and self
// 4. auto scroll the control while the cursor near the top
// or bottom of the control
// usage :
// In the 4 event functions call the bwXXXX
// event : StartDrag/EndDrag/DragOver/DragDrop
uses windows, classes, Controls, Forms, ComCtrls, ExtCtrls;
var
lastitem, dragitem : TTreeNode;
DragTimer : TTimer;
procedure bwTreeViewStartDrag(Sender: TObject;
var DragObject: TDragObject; timer1 : TTimer = nil);
procedure bwTreeViewEndDrag(Sender, Target: TObject; X, Y: Integer);
procedure bwTreeViewDragDrop(Sender, Source: TObject; X, Y: Integer);
procedure bwTreeViewDragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
// Timer used to expand / collasp automatically
procedure bwtimer(Sender : TObject);
implementation
procedure bwTreeViewStartDrag(Sender: TObject;
var DragObject: TDragObject; timer1 : TTimer);
begin
DragItem := (Sender as TTreeView).selected;
lastitem := nil;
DragTimer := Timer1;
if Assigned(DragTimer) then
begin
DragTimer.Enabled := False;
end;
end;
procedure bwTreeViewEndDrag(Sender, Target: TObject; X, Y: Integer);
begin
if Assigned(DragTimer) then
DragTimer.Enabled := false;
end;
procedure bwTreeViewDragDrop(Sender, Source: TObject; X, Y: Integer);
var
DropItem : TTreeNode;
begin
if Source = Sender then
begin
DropItem := (Sender as TTreeView).GetNodeAt (x, y);
dragitem.MoveTo(DropItem, naAddChild);
end;
end;
procedure bwTreeViewDragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
var
DropItem, TopItem : TTreeNode;
rt : TRect;
begin
Accept := False;
if Source = Sender then
begin
DropItem := (Sender as TTreeView).GetNodeAt (x, y);
if DropItem = nil then
begin
if Assigned(DragTimer) then
DragTimer.Enabled := False;
Exit;
end;
if DropItem <> lastitem then
begin
if Assigned(DragTimer) then
begin
DragTimer.Enabled := False;
DragTimer.Enabled := True;
end;
Lastitem := DropItem;
end;
// if on the top , auto scroll
if DropItem = (Sender as TTreeView).topitem then
begin
if (Sender as TTreeView).topitem.GetPrevVisible <> nil then
(Sender as TTreeView).topitem :=
(Sender as TTreeView).topitem.GetPrevVisible;
if DropItem <> (Sender as TTreeView).topitem then
Exit;
end;
rt := dropItem.DisplayRect (False);
//// if on the bottom, auto scroll
if rt.Bottom > (Sender as TTreeView).Height - 8 then
begin
TopItem := (Sender as TTreeView).topitem;
if (Sender as TTreeView).topitem.GetNextVisible <> nil then
(Sender as TTreeView).topitem :=
(Sender as TTreeView).topitem.GetNextVisible;
if Topitem <> (Sender as TTreeView).topitem then
Exit;
end;
if DropItem = DragItem then// nothing
else
if DropItem.HasAsParent ( DragItem) = False then// not children
Accept := True;
if DragItem.HasAsparent(DropItem) = True then// don't collasp parent node
if Assigned(DragTimer) then
DragTimer.Enabled := False;
end;
end;
procedure bwtimer(Sender : TObject);
begin
if lastitem <> nil then
lastItem.Expanded := not LastItem.expanded;// expand/collaps automatically
end;
end.
|