Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to save/load to/from file in virtualtree component using Delphi?

Tags:

delphi

I have downloaded the virtualtree component and the manual"Virtual TreeView tutorial". I follow the tutorial and coding step by step. Most of the function in tutorial is fine except the savetofile and loadfromfile do not work.

My node data is

type
  PMytreedata = ^TMYTreeData;
  TMYTreeData = record
    Column0: String;
    Column1: String;
    Column2: String;
  end;

The question is something string lose in column0,column1/2 when load from file.

The code is below

Create new node and data:

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;

Save to file and load from file

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

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

Get the node size without the code error

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

Show text

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;

LOAD FORM FILE

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;

SAVE TO FILE

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;
like image 456
u950321 Avatar asked Mar 09 '23 09:03

u950321


1 Answers

In Unicode Delphi, 2009 and later, Char is a 16 bit type, WideChar. You are only writing half of the string because you don't account for this. In each call to Write and Read for the content of the string, you must write twice as many bytes.

For instance, each line like this

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

should be

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

Some other comments:

  • You replicate code to read and write each string. It would be better practise to extract those repeated sections of code into methods for re-use.
  • You should use WriteBuffer rather than Write. WriteBuffer calls Write to do the work, but also checks the return value and performs error checking. Likewise call ReadBuffer rather than Read.
like image 159
David Heffernan Avatar answered May 10 '23 17:05

David Heffernan