Magno 4 Posted December 15, 2022 Yes, Delphi 4.... Let's go, if you can help. I have a tree view with some nodes, like below I need to, eg., copy the select node (1.1.1) into 1.1.1.2 ! I've trying to figure out how to accomplish this. I already have a copy/past function that works well if no such complex copy is required, like copy a top node into a lower child node. The recursive function goes crazy with this lol I found some solutions but mostly will use newer version of Delphi so it won't work. One of the solutions I found was that: https://www.swissdelphicenter.ch/en/showcode.php?id=1876 But it won't allow me to copy into the same branch from a top level. I would appreciate any help on this! Share this post Link to post
programmerdelphi2k 237 Posted December 15, 2022 (edited) Here, you dont needs a "recursive" function!!! because that if you dont controls it, you know what happens... 🤣 We can use drag-n-drop's "automatic" mode to use less code! Afterwards, we need to know which "node" was selected and dragged, for that we can use two TreeView functions: "GetHitTestInfoAt(X, Y);" and "GetNodeAt(X, Y);" After that, we need to test where the "clicks" occurred in the TreeView; And finally, decide whether we are "Inserting" or "Adding" items to an existing "Node"! However, all this will happen after the "target" accepts or rejects the "Drag-n-drop" action! Here my sample about this situation: you can drag-n-drop in the same TV or to other you free for move to any place on TV: to root or any other level! type TForm1 = class(TForm) TreeView1: TTreeView; procedure TreeView1DragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); procedure TreeView1DragDrop(Sender, Source: TObject; X, Y: Integer); procedure FormCreate(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); begin TreeView1.DragMode := TDragMode.dmAutomatic; TreeView1.FullExpand; end; procedure TForm1.TreeView1DragDrop(Sender, Source: TObject; X, Y: Integer); var Node : TTreeNode; AttachMode: TNodeAttachMode; HT : THitTests; begin AttachMode := TNodeAttachMode.naAdd; // if TreeView1.Selected = nil then exit; // HT := TreeView1.GetHitTestInfoAt(X, Y); Node := TreeView1.GetNodeAt(X, Y); // if ((HT - [htOnItem, htOnIcon, htNowhere, htOnIndent]) <> HT) then begin if ((htOnItem in HT) or (htOnIcon in HT)) then AttachMode := naAddChild else if (htNowhere in HT) then AttachMode := naAdd else if (htOnIndent in HT) then AttachMode := naInsert; // TreeView1.Selected.MoveTo(Node, AttachMode); // TreeView1.FullExpand; end; end; procedure TForm1.TreeView1DragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); begin Accept := true; end; end. Edited December 15, 2022 by programmerdelphi2k 1 1 Share this post Link to post
Magno 4 Posted December 16, 2022 (edited) I need to do it programmatically, I will try use your idea to see if I can do it now, but I tested and was able only to move and not adding or inserting. Thanks!!! Edited December 16, 2022 by Magno Share this post Link to post
David Heffernan 2345 Posted December 16, 2022 5 hours ago, Magno said: I need to do it programmatically, I will try use your idea to see if I can do it now, but I tested and was able only to move and not adding or inserting. Thanks!!! Yeah, I think you can ignore that answer, it's really not relevant to your question. What you are trying to do is possible by iterating over the node and its children. I would start with some code to do that iteration. Do you have such code? 2 Share this post Link to post
Magno 4 Posted December 16, 2022 I am attaching a simple functional demo I just did with the code I am using. It has 3 buttons, one to select the source node, other to the destination (target) and the copy button itself. I works fine, but not if you try to copy a "father" node into it's on child, no problem to copy into another branch, like the 2nd image in the initial message here. I am really happy if you can help me because I am struggling for about 2 days on it, maybe a technique to make the node "understand" where it should stop when it's into the same branch, because only seeing if the node is nil isn't enough as by the recursive method we will have always something to iterate with this specific case and it will blow the memory. Maybe casting a class into the Data, or mark its pointer memory address, I dunno what could be the best. I am still trying something here. CopyTreeView.rar Share this post Link to post
Lajos Juhász 293 Posted December 16, 2022 You should place the nodes after a copy in a list, during the copy operation you have to skip those nodes. Share this post Link to post
aehimself 396 Posted December 16, 2022 Result: The code was written in D11 but I tried to keep it as simple as possible. I hope D4 supports the below calls... Type TTreeNodes = Array Of TTreeNode; procedure TForm1.Button3Click(Sender: TObject); Var added: TTreeNodes; begin SetLength(added, 0); CopyNodes(Source, Target, added); Target.Expanded := true; end; function TForm1.IsInArray(inTreeNode: TTreeNode; inArray: TTreeNodes): Boolean; Var a: Integer; begin Result := False; For a := 0 To Length(inArray) - 1 Do If inArray[a] = inTreeNode Then Begin Result := True; Exit; End; end; procedure TForm1.CopyNodes(inSource, inDestination: TTreeNode; var inCopied: TTreeNodes); Var a: Integer; tv: TTreeView; tn: TTreeNode; begin tv := inSource.TreeView As TTreeView; For a := 0 To inSource.Count - 1 Do Begin If Not IsInArray(inSource.Item[a], inCopied) Then Begin tn := tv.Items.AddChild(inDestination, inSource.Item[a].Text); // Do data copying, whatever SetLength(inCopied, Length(inCopied) + 1); inCopied[Length(inCopied) - 1] := tn; If inSource.Item[a].Count > 0 Then CopyNodes(inSource.Item[a], tn, inCopied); End; End; end; 1 Share this post Link to post
Magno 4 Posted December 16, 2022 3 hours ago, aehimself said: Result: The code was written in D11 but I tried to keep it as simple as possible. I hope D4 supports the below calls... Worked like a charm!!! I didn't though using arrays lol.. I love programming because of this! I will convert back to my real code. I just want to check all the behavior, but so far so good. Thank you very much for you time!! 3 hours ago, aehimself said: Share this post Link to post
aehimself 396 Posted December 16, 2022 A TList would be better choice but I'm not sure D4 has it... that's why I settled with an array. Share this post Link to post
Magno 4 Posted December 19, 2022 On 12/16/2022 at 3:09 PM, aehimself said: A TList would be better choice but I'm not sure D4 has it... that's why I settled with an array. Yes I has and I thought to move to a TList, but this way is working too! Thank you!! Share this post Link to post