|
Any class which descends from TPersistent is streamable. What gets streamed,
typically, are the properties in the __published section. However, it is possible
to stream "behind-the-scenes" data as well. The following class shows
how this is done.
//---------------------------------------------------------------------------
#ifndef aStringObjectH
#define aStringObjectH
#include <SysUtils.hpp>
#include <Controls.hpp>
#include <Classes.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
class aStringObject: public TPersistent
{
public:
__fastcall aStringObject(void){};
__fastcall aStringObject(String
theString){myString = theString;};
__fastcall aStringObject(aStringObject
&theStringObject){myString = theStringObject.AsString;};
operator String(void){return myString;};
aStringObject &operator = (String
theString){myString = theString; return *this;};
void __fastcall ReadData(TReader
*theReader)
{
myString = theReader->ReadString();
};
void __fastcall WriteData(TWriter
*theWriter)
{
theWriter->WriteString(myString);
};
void __fastcall DefineProperties(TFiler*
theFiler)
{
bool HasData
= false;
if (theFiler->Ancestor
!= NULL) // This is on a descendant form
{
aStringObject
*AncestorObject = dynamic_cast<aStringObject *>(theFiler->Ancestor);
if
(AncestorObject != NULL)
{
HasData
= !(myString == *AncestorObject);
}
else
{
HasData
= true;
};
}
else
{
HasData
= true;
};
theFiler->DefineProperty("String",ReadData,WriteData,HasData);
};
int __fastcall Length(void){return
myString.Length();};
__property String AsString = {read=myString,write=myString};
private:
String myString;
};
#endif
|
As you can see, this is simply a wrapper class for an AnsiString. What is most
important is that it shows how to define streaming for the non-published String
property. This can work with any non-published data, including conventional
variables, structs, binary data, etc.
The class exploits the streaming system to store and retrieve the non-published
sub-property String. This entails overriding ReadData, WriteData, and DefineProperties
(the function that tells the streaming system to use ReadData and WriteData).
The special HasData and AncestorObject tests in the DefineProperties checks
to see if this is a property in a component on a descendant form. If it is,
it checks to see if the property value is different on the current (descendant)
form from that on the ancestor form, and only saves the hidden property string
if the value is different. This is essential to properly support form inheritance.
|
|