Delphi类和组件 - TreeView 智能拖拽
属性:
TreeView:需要实现拖拽功能的 TreeView,当把一个 TreeView
指定给该属性后,这个 TreeView 的节点就具有智能拖拽功能了。
DragMode = dmHotKeyDrag // 通过快捷键才能拖拽
HotKeyMoveNode = hkCtrl; // 拖拽节点: Ctrl
HotKeyCopyNode = hkShift; // 拖拽并复制节点:Shift
HotKeyChildNode = hkAlt; // 拖拽到子节点:Alt
EnableRButtonDrag = True; // 允许右键拖拽,会弹出菜单
Public 方法:
AddNode:添加节点,根据 AddMode 决定添加的位置
DeleteNode:删除节点,返回被删除节点临近的节点
MoveNode:移动或复制节点,根据 MoveMode 决定移动方式
******************************************************* }
unit TreeViewManage;
inte易做图ce
uses
SysUtils, Windows, Classes, Controls, ComCtrls, Menus;
type
TAttachMode = (amLast, amFirst, amChildLast, amChildFirst, amPrev,
amNext, amAuto);
{ 控制拖拽方式的热键:禁止,Ctrl,Shift,Alt }
THotKey = (hkNone, hkCtrl, hkShift, hkAlt);
{ 节点拖动方式:自动拖拽,热键拖拽,禁止拖拽 }
TDragMode = (dmAutoDrag, dmHotKeyDrag, dmDisableDrag);
TTreeViewDrager = class(TComponent)
private
FTreeView: TTreeView;
FOldOnMouseDown: TMouseEvent;
FOldOnMouseUp: TMouseEvent;
FOldOnDragOver: TDragOverEvent;
FOldOnDragDrop: TDragDropEvent;
FDragMode: TDragMode; { 节点拖动方式 }
FDragButton: TMouseButton; { 拖动节点的按钮 }
FDropMenu: TPopupMenu; { 右键拖拽后的弹出菜单 }
FMoveSourceNode: TTreeNode; { 移动的源节点 }
FMoveTargetNode: TTreeNode; { 移动的目标节点 }
FHotKeyMoveNode: Integer; { 拖动节点的热键 }
FHotKeyCopyNode: Integer; { 复制节点的热键 }
FHotKeyChildNode: Integer; { 拖动到子节点的热键 }
FEnableRButtonDrag: Boolean; { 是否允许右键拖拽,右键拖拽会弹出菜单 }
function GetTreeView: TCustomTreeView;
procedure SetTreeView(Value: TCustomTreeView);
function GetHotKeyMoveNode: THotKey;
procedure SetHotKeyMoveNode(Key: THotKey);
function GetHotKeyCopyNode: THotKey;
procedure SetHotKeyCopyNode(Key: THotKey);
function GetHotKeyChildNode: THotKey;
procedure SetHotKeyChildNode(Key: THotKey);
procedure MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
procedure DragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
procedure DragDrop(Sender, Source: TObject; X, Y: Integer);
protected
function CreateDropMenu: TPopupMenu; virtual;
procedure DragMenuEvent(Sender: TObject); virtual;
function GetNewNode(RelativeNode: TTreeNode = nil; NodeName: string = '';
AddMode: TAttachMode = amAuto): TTreeNode;
function CloneNode(FromNode, ToNode: TTreeNode;
MoveMode: TAttachMode = amAuto): TTreeNode;
procedure CopyChildNodes(FromNode, ToNode: TTreeNode); virtual;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
function AddNode(RelativeNode: TTreeNode = nil; NodeName: string = '';
AddMode: TAttachMode = amAuto): TTreeNode; virtual;
function DeleteNode(RelativeNode: TTreeNode): TTreeNode; virtual;
function MoveNode(FromNode, ToNode: TTreeNode;
MoveMode: TAttachMode = amAuto; bCopy: Boolean = False)
: TTreeNode; virtual;
published
property TreeView: TCustomTreeView read GetTreeView Write SetTreeView;
property DragMode: TDragMode read FDragMode Write FDragMode
default dmHotKeyDrag;
property HotKeyMoveNode: THotKey read GetHotKeyMoveNode
write SetHotKeyMoveNode default hkCtrl;
property HotKeyCopyNode: THotKey read GetHotKeyCopyNode
write SetHotKeyCopyNode default hkShift;
property HotKeyChildNode: THotKey read GetHotKeyChildNode
write SetHotKeyChildNode default hkAlt;
property EnableRButtonDrag: Boolean read FEnableRButtonDrag
write FEnableRButtonDrag default True;
end;
const
{ 由于 Delphi 的 TreeView 所能管理的最大节点数为 65535,所以这里给出范围限制 }
MaxNodeCount = 65535;
resourcestring
Error_NodeOutOfRange = '警告:TreeView 节点数达到最大限制:%d,无法继续添加节点';
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Samples', [TTreeViewDrager]);
end;
{ 判断按键是否被按下 }
function IsKeyDown(VK: Integer): Boolean;
begin
Result := GetKeyState(VK) < 0;
end;
constructor TTreeViewDrager.Create(AOwner: TComponent);
begin
inherited;
FDragMode := dmHotKeyDrag;
HotKeyMoveNode := hkCtrl;
HotKeyCopyNode := hkShift;
HotKeyChildNode := hkAlt;
FDropMenu := CreateDropMenu;
FEnableRButtonDrag := True;
end;
destructor TTreeViewDrager.Destroy;
begin
FDropMenu.Free;
inherited;
end;
{ ------------------------------------------------------------ }
{ 拖放后的弹出菜单 }
{ ------------------------------------------------------------ }
function TTreeViewDrager.CreateDropMenu: TPopupMenu;
const
DropMenuName: array [1 .. 9] of PChar = ('移动到之前(&1)', '移动到之后(&2)',
'移动到子节点最前(&5)', '移动到子节点最后(&6)', '-', '复制到之前(&A)', '复制到之后(&B)',
'复制到子节点最前(&E)', '复制到子节点最后(&F)');
var
I: Integer;
NewItem: TMenuItem;
begin
Result := TPopupMenu.Create(FTreeView);
for I := Low(DropMenuName) to High(DropMenuName) do
begin
NewItem := TMenuItem.Create(FTreeView);
NewItem.Tag := I;
NewItem.OnClick := DragMenuEvent;
NewItem.Caption := DropMenuName[I];
Result.Items.Add(NewItem);
end;
end;
procedure TTreeViewDrager.DragMenuEvent(Sender: TObject);
const
MoveMode: array [1 .. 4] of TAttachMode = (amPrev, amNext, amChildFirst,
amChildLast);
var
bCopy: Boolean;
Inde
补充:软件开发 , Delphi ,