如何使用Delphi在virtualtree组件中保存/加载到/从文件中加载?

如何使用Delphi在virtualtree组件中保存/加载到/从文件中加载?,delphi,Delphi,我已经下载了virtualtree组件和手册“VirtualTreeView教程”。我按照教程一步一步地编写代码。除了savetofile和loadfromfile不起作用外,本教程中的大部分函数都很好 我的节点数据是 type PMytreedata = ^TMYTreeData; TMYTreeData = record Column0: String; Column1: String; Column2: String; end; 问题是从文件加载时,第

我已经下载了virtualtree组件和手册“VirtualTreeView教程”。我按照教程一步一步地编写代码。除了savetofile和loadfromfile不起作用外,本教程中的大部分函数都很好

我的节点数据是

type
  PMytreedata = ^TMYTreeData;
  TMYTreeData = record
    Column0: String;
    Column1: String;
    Column2: String;
  end;
问题是从文件加载时,第0列、第1/2列中的字符串丢失了一些内容

代码如下

创建新节点和数据:

procedure TForm3.Button1Click(Sender: TObject); //CRETAE NEW NODE AND DATA
begin
  Randomize;
  Rand := Random(99);
  XNode := VST.AddChild(nil);

  if VST.AbsoluteIndex(XNode) > -1 then
  begin
    Data := VST.GetNodeData(Xnode);
    Data^.Column0 := IntToStr(Rand)+EDIT1.Text + 'One' ;
    Data^.Column1 := EDIT1.Text+'Two' + IntToStr(Rand + 10);
    Data^.Column2 := EDIT1.Text+'Three' + IntToStr(Rand - 10);
  end;
end;

procedure TForm3.Button2Click(Sender: TObject);//ADDCHILD
var
  XNode: PVirtualNode;
  Data: PMytreedata;
begin
  if not Assigned(VST.FocusedNode) then
     Exit;

   XNode := VST.AddChild(VST.FocusedNode);
   Data := VST.GetNodeData(Xnode);

   Data^.Column0 := EDIT1.Text ;
   Data^.Column1 := EDIT2.Text ;
   Data^.Column2 := EDIT3.Text ;

   VST.Expanded[VST.FocusedNode] := True;
end;
保存到文件并从文件加载

procedure TForm3.Button4Click(Sender: TObject);
begin
    VST.SaveToFile('C:\vst.at1');
end;

procedure TForm3.Button5Click(Sender: TObject);
begin
    VST.LoadFromFile('C:\vst.at1');
end;
获取没有代码错误的节点大小

procedure TForm3.VSTGetNodeDataSize(Sender: TBaseVirtualTree;
  var NodeDataSize: Integer);
begin
    NodeDataSize := SizeOf(TMYTreeData);//WITHOUT THE CODE,ERROR COMING .
end;
显示文本

procedure TForm3.VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
var
  Data: PMytreedata;
begin
  Data := VST.GetNodeData(Node);
  case Column of
    0: CellText := Data^.Column0;
    1: CellText := Data^.Column1;
    2: CellText := Data^.Column2;
  end;
end;
加载表单文件

procedure TForm3.VSTLoadNode(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Stream: TStream);//LOAD FORM FILE
var
  Data: PMytreedata;
  Len: Integer;
begin
      Data := VST.GetNodeData(Node);

      Stream.read(Len, SizeOf(Len));
      SetLength(Data^.Column0, Len);
      Stream.read(PChar(Data^.Column0)^, Len);

      Stream.read(Len, SizeOf(Len));
      SetLength(Data^.Column1, Len);
      Stream.read(PChar(Data^.Column1)^, Len);

      Stream.read(Len, SizeOf(Len));
      SetLength(Data^.Column2, Len);
      Stream.read(PChar(Data^.Column2)^, Len);
end;
保存到文件

procedure TForm3.VSTSaveNode(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Stream: TStream); //SAVE TO FILE
var
  Data: PMytreedata;
  Len: Integer;
begin
  Data := VST.GetNodeData(Node);

  Len := Length(Data^.Column0);
  Stream.write(Len, SizeOf(Len));
  Stream.write(PChar(Data^.Column0)^, Len);

  Len := Length(Data^.Column1);
  Stream.write(Len, SizeOf(Len));
  Stream.write(PChar(Data^.Column1)^, Len);

  Len := Length(Data^.Column2);
  Stream.write(Len, SizeOf(Len));
  Stream.write(PChar(Data^.Column2)^, Len);
end;

在Unicode Delphi,2009及更高版本中,
Char
是一种16位类型,
WideChar
。您只写了字符串的一半,因为您没有考虑这一点。对于字符串的内容,在每次调用
Write
Read
时,必须写入两倍的字节

比如说,每一行都是这样的

Stream.read(PChar(Data^.Column0)^, Len);
应该是

Stream.read(PChar(Data^.Column0)^, Len*SizeOf(Char));
其他一些评论:

  • 您可以复制代码来读写每个字符串。更好的做法是将这些重复的代码段提取到方法中以供重用
  • 您应该使用
    WriteBuffer
    而不是
    Write
    WriteBuffer
    调用
    Write
    来执行该工作,但也会检查返回值并执行错误检查。同样,调用
    ReadBuffer
    而不是
    Read

我没有使用writebuffer的经验。我测试过了,效果很好。谢谢你快速准确的解决方案。谢谢