|
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);
}
}
//---------------------------------------------------------------------------
|
|