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

An Aggregate With Exposed and Streamable Subcomponents

 

This example provides an aggregate component that lets you click on its subcomponents and edit them in the object inspector. You can rearrange or alter any properties of the subcomponents.

.h

//---------------------------------------------------------------------------

#ifndef StreamableAggregateHostPanelH
#define StreamableAggregateHostPanelH
//---------------------------------------------------------------------------
#include <SysUtils.hpp>
#include <Controls.hpp>
#include <Classes.hpp>
#include <Forms.hpp>
#include "StreamableAggregatePanel.h"

//---------------------------------------------------------------------------
class PACKAGE TStreamableAggregateHostPanel : public TStreamableAggregatePanel
{
   /*
      This component class is a descendant of TStreamableAggregatePanel.
      The children are created each time, and their characteristics are streamed when
      saved at design time. Prior to the children being streamed in, the constructor
      children are deleted and the streamed instances replace them.

      The children are owned by the owner of this component and are parented
      by this component. The GetChildOwner function sets the owner to the
      form, and the read state function makes sure the child controls get
      deleted - this has to be done differently than it is done in TStreamableAggregatePanel,
      because the children are not owned by this component.

      The children have no name so that they will not conflict with the names
      of other components owned by the form. However, any property of any child
      can be changed at design time in the object inspector, including the name.
      The form will them complain if the name is changed to something not unique.
      This is possible because they are owned by the form.
   */

   private:
   protected:

      // These functions override those in TStreamableAggregatePanel to make
      // sure that the children are owned by the form, and that the constructor
      // created children are destroyed before the streamed instances are
      // streamed in.
   
      DYNAMIC TComponent* __fastcall GetChildOwner(void);
      void __fastcall ReadState(Classes::TReader* Reader);
      void __fastcall Loaded(void);

   public:

      __fastcall TStreamableAggregateHostPanel(TComponent* Owner);
      
   __published:
};
//---------------------------------------------------------------------------
#endif

.cpp

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "StreamableAggregateHostPanel.h"
#pragma package(smart_init)
//---------------------------------------------------------------------------
// ValidCtrCheck is used to assure that the components created do not have
// any pure virtual functions.
//

static inline void ValidCtrCheck(TStreamableAggregateHostPanel *)
{
   new TStreamableAggregateHostPanel(NULL);
}
//---------------------------------------------------------------------------
__fastcall TStreamableAggregateHostPanel::TStreamableAggregateHostPanel(TComponent* Owner)
   : TStreamableAggregatePanel(Owner)
{
   delete myChildButton; // Get rid of the ancestor class instance...
   myChildButton = NULL; // ... and make sure it isn't accidentally used

   // Create two new ones... We can't use name to distinguish between them because we can't predict what names are on the form, and because the user can change the names after they are added and before they are saved
   // Thus, we don't even keep them in variables

   CreateChildButton(Owner);
   
   TButton *SecondButton = CreateChildButton(Owner);
   SecondButton->Left = 80;
}
//---------------------------------------------------------------------------
TComponent* __fastcall TStreamableAggregateHostPanel::GetChildOwner(void)
{
   return NULL; // Owned by form
}
//---------------------------------------------------------------------------
void __fastcall TStreamableAggregateHostPanel::ReadState(Classes::TReader* Reader)
{
   for (int Index = ControlCount-1; Index >= 0; Index--) delete Controls[Index]; // DestroyComponents (as done in TStreamableAggregatePanel) won't work because the children are owned by the form

   TComponentClass StreamUsedClasses[1] =
   {
      __classid(TButton)
   };

   RegisterClasses(StreamUsedClasses,0); // Index is high position not count
   TAggregatePanel::ReadState(Reader);
}
//---------------------------------------------------------------------------
void __fastcall TStreamableAggregateHostPanel::Loaded(void)
{
   TPanel::Loaded(); // We can't set any characteristics of the streamed in controls, because the user can change any property including name; this is a little dangerous, though, if the inheritance hierarchy changes...
}
//---------------------------------------------------------------------------
namespace Streamableaggregatehostpanel
{
   void __fastcall PACKAGE Register()
   {
      TComponentClass classes[1] = {__classid(TStreamableAggregateHostPanel)};
      RegisterComponents("MSC Test", classes, 0);
   }
}
//---------------------------------------------------------------------------


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