Главная » Delphi » Основная » Как сохранить и загрузить TTreeview с данными.

Как сохранить и загрузить TTreeview с данными.

22:16
In article <3ba5b631_2@dnews>, Kiran wrote:
> Can some one help me out, on how to save a treeview with its data/node on
> to a file.
> Data is an object which can have its own save/load method.

Saving and loading a treeview with data

Type
{: Callback procedure to save the data for a node into a stream
via the passed writer. }

TNodeSaveDataProc =
Procedure( writer: TWriter; data: Pointer );
{: Callback function to load the data for a node from a stream
via the passed reader. }

TNodeLoadDataProc =
Function( reader: TReader ): Pointer;
 
Procedure SaveTreeviewToStream( tv: TTreeview; S: TStream;
        saveProc: TNodeSaveDataProc );
Var
  writer: TWriter;
  node: TTreeNode;
Begin
  Assert( Assigned( tv ));
  Assert( Assigned( S ));
  Assert( Assigned( saveProc ));
  writer:= TWriter.Create( S, 4096 );
  try
    node:= tv.Items[0];
    writer.WriteListBegin;
    While node <> nil Do Begin
      writer.WriteInteger( node.level );
      writer.WriteString( node.Text );
      writer.WriteInteger( node.Imageindex );
      saveProc( writer, node.data );
      node:= node.GetNext;
    End; { While }
    writer.WriteListEnd;
    writer.FlushBuffer;
  finally
    writer.Free;
  end;
End; { SaveTreeviewToStream }
 
Procedure LoadTreeviewFromStream( tv: TTreeview; S: TStream;
                  loadProc: TNodeLoadDataProc );
Var
  reader: TReader;
  node: TTreenode;
  level: Integer;
Begin
  Assert( Assigned( tv ));
  Assert( Assigned( S ));
  Assert( Assigned( loadProc ));
  tv.Items.BeginUpdate;
  try
    tv.Items.Clear;
    reader:= TReader.Create( S, 4096 );
    try
      node:= nil;
      reader.ReadListBegin;
      While not Reader.EndOfList Do Begin
        level := reader.ReadInteger;
        If node = nil Then
        // create root node, ignore its level
          node:= tv.Items.Add( nil, '' )
        Else Begin
          If level = node.level Then
            node := tv.Items.Add( node, '' )
          Else If level > node.level Then
            node := tv.Items.AddChild( node, '' )
          Else Begin
            While Assigned(node) and (level < node.level) Do
              node := node.Parent;
            node := tv.Items.Add( node, '' );
          End; { Else }
        End; { Else }
        node.Text := Reader.ReadString;
        node.ImageIndex := Reader.ReadInteger;
        node.Data := loadProc( Reader );
      End; { While }
      reader.ReadListEnd;
    finally
      reader.Free;
    end;
  finally
    tv.items.Endupdate;
  end;
End; { LoadTreeviewFromStream }

The complete logic for saving/loading the data (e.g. objects) associated
to the nodes is external to the two routines above and implemented
by two callback routines you have to write and pass to the save/load
routines. These callbacks encapsulate the knowledge specific to the
object or data you need to save. If you want to save objects of a
particular class, and if the class has been designed well, the routines
may look like this:

Procedure SaveMyObject( writer: TWriter; data: Pointer );
Begin
  writer.Writeboolean( Assigned(data));
  If Assigned(data) Then Begin
    Assert( TObject(data) Is TMyObject );
    TMyObject(data).Save( writer );
  End;
End;
 
Function LoadMyObject( reader: TReader ): Pointer;
Var
  obj: TMyObject;
Begin
  If reader.Readboolean Then Begin
    obj:= TMyObject.Create;
    obj.Load( reader );
    Result := obj;
  End { If }
  Else
    Result := nil;
End;

This way the eventual work of storing or loading the objects data
ends up where it belongs: with the object itself. The Save and Load
methods are ones you have to write yourself, of course.

Peter Below (TeamB) 100113.1101@compuserve.com)
No e-mail responses, please, unless explicitly requested!
Note: I'm unable to visit the newsgroups every day at the moment,
so be patient if you don't get a reply immediately.