Delphi 如何将TTreeview保存到Windows并保持其层次结构?

Delphi 如何将TTreeview保存到Windows并保持其层次结构?,delphi,Delphi,我希望能够将我的Treeview保存到Windows并保持其层次结构,但似乎无法理解递归的魔力 假设我有两种不同的对象类型: TMyFolderNode (represents a folder in the tree) TMyItemNode (represents a node containing a stringlist of text for example) 树视图将在运行时填充,对于添加的每个节点,都包含指向这些对象之一的指针-通常,TMyFolderNode将表示TMyItem

我希望能够将我的Treeview保存到Windows并保持其层次结构,但似乎无法理解递归的魔力

假设我有两种不同的对象类型:

TMyFolderNode (represents a folder in the tree)
TMyItemNode (represents a node containing a stringlist of text for example)
树视图将在运行时填充,对于添加的每个节点,都包含指向这些对象之一的指针-通常,TMyFolderNode将表示TMyItemNode的子节点的父节点

所以基本上,如果我的树视图是这样的:

..\Vehicles
..\Vehicles\Bikes
..\Vehicles\Cars
..\Vehicles\Cars\Classic
..\Vehicles\Cars\Classic\1996 Shelby Cobra.txt
..\Vehicles\Cars\Classic\Corvette Stingray.txt
..\Vehicles\Cars\Classic\Jaguar E-Type.txt
..\Vehicles\Cars\Tuner
..\Vehicles\Cars\Tuner\Toyota Supra RZ.txt
..\Vehicles\Trucks
保存treeview时,Windows中的结构应如下所示:

..\Vehicles
..\Vehicles\Bikes
..\Vehicles\Cars
..\Vehicles\Cars\Classic
..\Vehicles\Cars\Classic\1996 Shelby Cobra.txt
..\Vehicles\Cars\Classic\Corvette Stingray.txt
..\Vehicles\Cars\Classic\Jaguar E-Type.txt
..\Vehicles\Cars\Tuner
..\Vehicles\Cars\Tuner\Toyota Supra RZ.txt
..\Vehicles\Trucks
这就是我所尝试的:

procedure SaveTreeViewStructure(TreeView: TTreeView; const OutDirectory: string);
var
  RootDir, SubDir: string;
  Node: TTreeNode;

  // the recursive procedure
  procedure SaveNode(Node: TTreeNode);
  var
    Obj: TObject;
    Child: TTreeNode;
  begin
    Obj := TObject(Node.Data);

    // node type is a folder/parent, so create the folder in windows...
    if Obj.ClassType = TMyFolderNode then
    begin
      ForceDirectories(RootDir + '\' + Node.Text);
    end;

    // node is a type holding data we can save to text file...
    if Obj.Create.ClassType = TMyItemNode then
    begin
      with TMyItemNode(Obj) do
      begin
        // save the file as .txt...
      end;
    end;

    Child := Node.GetFirstChild;
    while Assigned(Child) do
    begin
      SaveNode(Child);
      Child := Child.GetNextSibling;
    end;
  end;

begin
  RootDir   := OutDirectory + '\';
  SubDir    := '';
  Node      := nil;

  if ForceDirectories(RootDir) then // make sure base folder exists first
  begin
    Node := TreeView.Items[0]; // start from the first tree node (TopItem causes problems)
    while Assigned(Node) do // until node is no longer assigned
    begin
      SaveNode(Node); // call the recursive procedure
      Node := Node.GetNextSibling; // go to the next node
    end;
  end;
end;
如果我尝试只保存TMyFolderNode节点,它们不会在适当的子文件夹等中创建,然后当我尝试保存文本TMyItemNode时,我无法找到文件错误,可能是因为文件夹保存不正确

显然,我不完全理解递归背后的逻辑,我知道这意味着在满足条件之前调用它自己,例如我们到达树中的最后一个节点,但我似乎无法理解这一点

那么,如何将我的Treeview保存到Windows中的一个基本文件夹中,递归过程将在其中创建所需的子目录,并将常规节点项保存在正确的位置

我的方法错了吗?我第一次尝试了for循环,但是文件夹一直在翻倍和其他奇怪的事情


非常感谢。

正如500-内部服务器错误所指出的,答案是更改我传递给递归过程的路径

我还必须以字符串格式获取节点的路径,然后将其用作新路径:

function NodeToStringPath(Node: TTreeNode; var Path: string): string;
begin
  Result := '';

  Path := Node.Text + '\' + Path;
  if Node.Level = 0 then
  begin
    Result := Path
  end
  else
    Result := NodeToStringPath(Node.Parent, Path);
end;

function RemoveLastFolder(var S: string): string;
begin
  Result := '';

  repeat
    Delete(S, Length(S), 1)
  until
    (S[Length(S)] = '\') or (S = '');

  Result := S;
end;

procedure SaveTreeViewStructure(TreeView: TTreeView; const OutDirectory: string);
var
  RootDir, SubDir: string;
  Node: TTreeNode;

  // the recursive procedure
  procedure SaveNode(Node: TTreeNode);
  var
    sPath: string;
    Obj: TObject;
    Child: TTreeNode;
  begin
    Obj := TObject(Node.Data);

    // node type is a folder/parent, so create the folder in windows...
    if Obj.ClassType = TMyFolderNode then
    begin
      SubDir := NodeToStringPath(Child, sPath);
      ForceDirectories(RootDir + SubDir);
    end;

    // node is a type holding data we can save to text file...
    if Obj.Create.ClassType = TMyItemNode then
    begin
      with TMyItemNode(Obj) do
      begin
        // save the file as .txt...
        SubDir := NodeToStringPath(Node, sPath);
        SubDir := RemoveLastFolder(SubDir);
        //...
      end;
    end;

    Child := Node.GetFirstChild;
    while Assigned(Child) do
    begin
      SaveNode(Child);
      Child := Child.GetNextSibling;
    end;
  end;

begin
  RootDir   := OutDirectory + '\';
  SubDir    := '';
  Node      := nil;

  if ForceDirectories(RootDir) then // make sure base folder exists first
  begin
    Node := TreeView.Items[0]; // start from the first tree node (TopItem causes problems)
    while Assigned(Node) do // until node is no longer assigned
    begin
      SaveNode(Node); // call the recursive procedure
      Node := Node.GetNextSibling; // go to the next node
    end;
  end;
end;
经过测试,似乎可以工作,但它不是100%,但在尝试保存文本文件节点类型时,我需要从字符串中删除文件夹名称的最后一部分,这也很麻烦


我确信有一种更干净的方法可以实现这一点,但这是我能做到的最好的方法,我只需要调整一些东西,但要将树状视图的结构保存到windows,感觉需要做很多工作。

而不是在递归过程中直接使用RootDir,将相对路径作为参数传入,并根据需要附加到该路径。@500 InternalServerError谢谢提示,我想我已经可以使用了,但现在没有时间进行测试。我所做的是获取字符串的节点路径,然后将其作为文件路径传递。我将在稍后发布我更改的内容,希望在稍后测试时它能正常工作。@500 InternalServerError我发布了我的答案,但如果您愿意,您也可以发布您的解决方案: