V dnešním dílu ve znamení tří jedniček se trochu jemně dotkneme tématu technologie drag & drop. Ukážeme si, jak pomocí tohoto způsobu přesunovat jednotlivé větve v rámci TreeView.
Oč jde při
drag & drop vám určitě nemusím říkat, protože tato technologie je v systémech Windows již dlouho. Umožňuje uživateli uchopit myší nějaký objekt (např. soubor, zástupce apod.), přesunout jej jinam a zde jej opět pustit (např. vyhodit do koše). Převážně se tohoto postupu používá právě při rozličné manipulaci se soubory, ale rozhodně to není pravidlo.
Detailnějšímu popisu fungování této technologie v Delphi se vyhneme, protože to patří do jiného seriálu a dnes si ukážeme, jak pomocí "táhni a pusť" přesouvat jednotlivé položky (větve) v rámci komponenty TreeView. Nebudeme tedy komunikovat s jinou aplikací ani s jinými objekty v rámci naší aplikace, ale pouze uvnitř samotného TreeView. Je to poměrně užitečná věc, protože pokud potřebujete přeuspořádat nějakou stromovou strukturu, je to tímto postupem pohybem myši velmi přirozené a pohodlné, což uživatel jistě ocení.
Přistupme tedy k našemu dnešnímu programu. Na formulář umístíme nejprve TreeView a naplňte jej rovněž nějakými testovacími daty. Snažte se vytvořit alespoň náznak nějaké stromové struktury, aby bylo vše při testování příkladu dobře zřetelné. Další důležitá věc je, že v Object Inspectoru musíme nastavit pro vlastnost DragMode hodnotu dmAutomatic. Tolik tedy k "vizuální" stránce a zbytek už je na zdrojovém kódu.
Vytvoříme si proceduru, která nám přesune v rámci daného TreeView vybranou větev z jednoho místa na druhé. Odkud, kam a jak, tak k tomu nám pomohou události OnDragDrop a OnDragOver našeho TreeView.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, StdCtrls;
type
TForm1 = class(TForm)
TreeView1: TTreeView;
procedure TreeView1DragDrop(Sender, Source: TObject; X, Y: Integer);
procedure TreeView1DragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
private
{ Private declarations }
procedure MoveNode(TargetNode, SourceNode : TTreeNode);
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.MoveNode(TargetNode, SourceNode : TTreeNode);
var
nodeTmp : TTreeNode;
i : Integer;
begin
with TreeView1 do
begin
nodeTmp := Items.AddChild(TargetNode, SourceNode.Text);
for i := 0 to SourceNode.Count -1 do
begin
MoveNode(nodeTmp, SourceNode.Item[i]);
end;
end;
end;
procedure TForm1.TreeView1DragDrop(Sender, Source: TObject; X, Y: Integer);
var
TargetNode, SourceNode : TTreeNode;
begin
with TreeView1 do
begin
TargetNode := GetNodeAt(X, Y);
SourceNode := Selected;
if (TargetNode = nil) then
begin
EndDrag(False);
Exit;
end;
MoveNode(TargetNode,SourceNode);
SourceNode.Free;
end;
end;
procedure TForm1.TreeView1DragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
begin
if (Sender = TreeView1) then
begin
Accept := True;
end;
end;
end.
Událost OnDragDrop zjistí, kterou větev a kam přemístit, a o zbytek se postará MoveNode. A poslední procedura, událost OnDragOver, zase hlídá, aby komponenta TreeView "přijímala" přesunuté větve jen sama od sebe a ne odjinud.