Delphi 中实现TVirtualStringTree鼠标拖动改变节点顺序

2017-07-29 14:09:21来源:oschina作者:我本一介布衣人点击

分享

之前在项目中使用了TVirtualStringTree控件来显示树结构,为了提高用户体验,需要实现通过鼠标拖拽来实现改变节点的位置。


需要实现TVirtualStringTree的三个事件,OnDragAllowed,OnDragOver,OnDragDrop。


在OnDragAllowed事件中我们设置控件是否允许拖拽。


procedure TForm1.VstDragAllowed(Sender: TBaseVirtualTree;
Node: PVirtualNode; Column: TColumnIndex; var Allowed: Boolean);
begin
Allowed := True; // 设置Allowed为true则代表节点可以支持拖动
end;

在OnDragOver事件中我们设置控件是否接受拖动,本例子中只支持当前控件内的拖动。


procedure TForm1.VstDragOver(Sender: TBaseVirtualTree; Source: TObject;
Shift: TShiftState; State: TDragState; Pt: TPoint; Mode: TDropMode;
var Effect: Integer; var Accept: Boolean);
begin
Accept := (Source = Sender); // 只允许当前控件的拖拽
end;

OnDragDrop为拖动完成事件,我们在此处可以完成想要实现的移动功能。


procedure TForm1.VstDragDrop(Sender: TBaseVirtualTree; Source: TObject;
DataObject: IDataObject; Formats: TFormatArray; Shift: TShiftState;
Pt: TPoint; var Effect: Integer; Mode: TDropMode);
var
pSource, pTarget: PVirtualNode;
attMode: TVTNodeAttachMode;
begin
pSource := TVirtualStringTree(Source).FocusedNode; // 原节点
pTarget := Sender.DropTargetNode; // 目标节点
{TDropMode = (
dmNowhere, // 没有释放位置
dmAbove, // DropTargetNode节点上方
dmOnNode,// 节点上面
dmBelow// 节点下面
);}
{// 移动动作
TVTNodeAttachMode = (
amNoWhere, // 不做任何操作
amInsertBefore, // 插入到目标节点前方
amInsertAfter,// 插入到目标节点后方
amAddChildFirst,// 插入作为目标节点的第一个子节点
amAddChildLast// 插入作为目标节点的最后一个子节点
);}
// 插入的模式
case Mode of
dmNowhere: attMode := amNoWhere;
dmAbove: attMode := amInsertBefore;
dmOnNode, dmBelow: attMode := amInsertAfter;
end;
// 进行移动
Sender.MoveTo(pSource, pTarget, attMode, False);
end;

通过实现这三个事件,我们就实现了鼠标拖动改变节点的顺序。实际开发过程中还需要考虑一些不允许拖动的情况,如子节点不能拖动到与父节点的父节点下方,父节点也不能拖动到子节点的下方等等。

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台