t e m p o r a l 
 d o o r w a y 

Streaming Classes

 

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.

Copyright © 2004 by Mark Cashman (unless otherwise indicated), All Rights Reserved