Board index » cppbuilder » Using a Frame Template inside a Component

Using a Frame Template inside a Component


2006-03-06 05:50:33 PM
cppbuilder107
If a component contains a number of controls it often becomes quite tedious
to create and position the controls in the component's constructor - as well
as set their relevant properties.
I've wondered and decided to investigate if it is possible to use a Frame
template inside the Component. It seems like a "best of both worlds"
solution - the controls are placed in a Frame (with BCB's support of "visual
designing" on Frames i.e. easy placement, editing, etc.). The Frame are then
used as the only Control in the Component - and typically the only thing
that needs to be done in the Component's constructor is to create the Frame
and set its Parent and Alignment.
This seems to work at first - the Component (containing its Frame) builds
and installs succesfully to the Palette. Placing the Component on a Form
also shows the Frame (with its child Controls) as expected. The project
(containing the Component) also builds successfully.
But the project crashes when run with the following error
(TPrFileDisplayFrame is the class name of the Frame - not the Component):
"Project Project2.exe raised exception class EClassNotFound with message
'Class TPrFileDisplayFrame not found'. Process stopped. Use Step or Run to
continue."
The project is stopped on on the application's main Form's constructor:
/* TCustomForm.Create */ inline __fastcall virtual
TForm(Classes::TComponent* AOwner) : TCustomForm( AOwner) { }
I'm somewhat non-plussed - Shouldn't the Frame then be compiled into the
Component library package? How can the Frame object successfully be resolved
during building of the app, but not when the app is run?
I am using Win2000 with BCB5 Update 1.
Regards,
Ettienne
 
 

Re:Using a Frame Template inside a Component

Following some advice found after searching the Web I tried to Register the
Frame class as follows:
namespace Tprfiledisplayframeunit
{
void __fastcall PACKAGE Register()
{
RegisterClass(__classid(TPrFileDisplayFrame));
}
}
//--------------------------------------------------------------------------
-
Note that 'TPrFileDisplayFrame' is the class name - derived from TFrame.
'Tprfiledisplayframeunit' is the namespace name - which is the same as the
Frame's CPP unit name. ('TPrFileDisplay' is the actual component class name
(derived from TPanel)).
Registering the class does not make any difference - I still get the same
'EClassNotFound ' error. Likewise, adding the RegisterClass() call to the
Component's Register procedure does not help - I still get the same error:
namespace Tprfiledisplay
{
void __fastcall PACKAGE Register()
{
TComponentClass classes[1] = {__classid(TPrFileDisplay)};
RegisterComponents("PRISM", classes, 0);
RegisterClass(__classid(TPrFileDisplayFrame));
}
}
//--------------------------------------------------------------------------
-
I guess I can still fall back on putting all the functionality in the Frame
templates (if all else fails) ...:-(
Any assistance will be appreciated.
Regards,
Ettienne
 

Re:Using a Frame Template inside a Component

I must be missing something since I can't replicate the error message. I
fully expected to be able to. What I've come up with is a situation where
the embedded frame is always there but any changes made to it on the form
are not stored in the DFM. Which might be what you're looking for anyhow.
I'm sure I'm just missing something in what I've created but here it is.
// Frame header (note, created visually and the global 'EmbedFrame'
// object has been removed from the code)
// unit = testEmbedFrame
class PACKAGE TEmbedFrame : public TFrame
{
__published: // IDE-managed Components
TButton *Button1;
private: // User declarations
public: // User declarations
__fastcall TEmbedFrame(TComponent* Owner);
};
// Control header
// unit = FrameComp
#include "testEmbedFrame.h"
class PACKAGE TFrameComp : public TCustomControl
{
typedef TCustomControl inherited;
private:
TEmbedFrame* fEmbedFrame;
void __fastcall set_EmbedFrame(TEmbedFrame* Value);
public:
__fastcall TFrameComp(TComponent* AOwner);
__published:
__property TEmbedFrame* EmbedFrame = {
read = fEmbedFrame, write = set_EmbedFrame };
};
// Control CPP
__fastcall TFrameComp::TFrameComp(TComponent* AOwner) : inherited(AOwner)
{
fEmbedFrame = new TEmbedFrame(this);
fEmbedFrame->Parent = this;
}
void __fastcall TFrameComp::set_EmbedFrame(TEmbedFrame* Value)
{
fEmbedFrame->Assign(Value);
}
namespace Framecomp
{
void __fastcall PACKAGE Register()
{
TMetaClass* components[] = { __classid(TFrameComp) };
RegisterComponents("Test", components, 0);
RegisterClass(__classid(TEmbedFrame)); // is of no consequence in this
// current scenario since the frame isn't getting stored in the DFM
}
}
Can you post your code so that I can see what you are doing. Also, I'm
using BCB6.
- Clayton
 

{smallsort}

Re:Using a Frame Template inside a Component

Thanks for the example Clayton. - it proved helpful to find the error. The
mistake I made was in the creation of the Frame object in the constructor of
the Component:
__fastcall TPrFileDisplay::TPrFileDisplay(TComponent* Owner) :
TPanel(Owner)
{
PrFileDisplayFrame = new TPrFileDisplayFrame(Owner);
//...
}
instead of:
__fastcall TPrFileDisplay::TPrFileDisplay(TComponent* Owner) :
TPanel(Owner)
{
PrFileDisplayFrame = new TPrFileDisplayFrame(this);
//...
}
This meant that the Owner of the Frame was the Form - causing the
EClassNotFound error. Once I had changed the owner of the Frame to the
Component everything worked.
Thanks again.
Ettienne