Как сохранить и загрузить 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.