Board index » cppbuilder » Component constructor seems not to executed Why ?

Component constructor seems not to executed Why ?


2005-07-25 11:47:15 PM
cppbuilder80
Hi,
I created a package which contains two classes TFirstClass and
TSecondClass. TSecondClass is an end-user VCL component.
TFirstClass is inherited from TComponent
TSecondClass is inherited from TFirstClass.
When I put my TSecondClass component on a form in the CBuilder
IDE. It seems that the constructor of TSecondClass is not
executed.
I can't resolve the problem. Could you help me.
Thanks for your answers.
Patrick
 
 

Re:Component constructor seems not to executed Why ?

Why do you say that the constructor does not execute?
Have you put a breakpoint on that line?
Perhaps you could show some code that shows what you are doing - we
shouldn't need to see any body code.
Rgds Pete
"Patrick Faure" < XXXX@XXXXX.COM >wrote in message
Quote

Hi,

I created a package which contains two classes TFirstClass and
TSecondClass. TSecondClass is an end-user VCL component.

TFirstClass is inherited from TComponent
TSecondClass is inherited from TFirstClass.

When I put my TSecondClass component on a form in the CBuilder
IDE. It seems that the constructor of TSecondClass is not
executed.

I can't resolve the problem. Could you help me.
Thanks for your answers.
Patrick

 

Re:Component constructor seems not to executed Why ?

"Patrick Faure" < XXXX@XXXXX.COM >wrote in message
Quote
I can't resolve the problem. Could you help me.
Not until you show the actual code first.
Gambit
 

{smallsort}

Re:Component constructor seems not to executed Why ?

"Patrick Faure" < XXXX@XXXXX.COM >wrote:
Quote

Hi,

I created a package which contains two classes TFirstClass and
TSecondClass. TSecondClass is an end-user VCL component.

TFirstClass is inherited from TComponent
TSecondClass is inherited from TFirstClass.

When I put my TSecondClass component on a form in the CBuilder
IDE. It seems that the constructor of TSecondClass is not
executed.

I can't resolve the problem. Could you help me.
Thanks for your answers.
Patrick

 

Re:Component constructor seems not to executed Why ?

Hi,
Thank you for your answer.
Here is my code.
- First class
class TADiComponent : public TComponent
{
protected:
TForm* FParentForm;
__property TForm* ParentForm = { read = FParentForm };
public:
__fastcall TADiComponent(TComponent* Owner);
};
-Second class
class PACKAGE TADiAppBar : public TADiComponent
{
private:
protected:
public:
__fastcall TADiAppBar(TADiComponent* Owner);
__fastcall ~TADiAppBar(void);
__published:
__property ParentForm;
};
// Constructor
__fastcall TADiComponent::TADiComponent(TComponent* Owner)
: TComponent(Owner)
{
FParentForm = (TForm*) Owner;
}
// Constructor
__fastcall TADiAppBar::TADiAppBar(TADiComponent* Owner)
:TADiComponent(Owner)
{
// TForm only owner ancestor type
if( !Owner->InheritsFrom( __classid( TForm ) ) )
throw Exception( LoadStr( ERROR001 ) );
// Only one ADiAppBar component
for( int i = 0; i < FParentForm->ComponentCount ; ++ i )
if( ( FParentForm->Components[i]->InheritsFrom( __classid( TADiAppBar ) )
&&
( FParentForm->Components[i] != this ) ) )
throw Exception( LoadStr( ERROR003 ) );
FParentForm->BorderStyle = bsToolWindow;
FParentForm->FormStyle = fsNormal;
// If not at design time set window style
if( !this->ComponentState.Contains( csDesigning ) )
{
RemoveWindowStyle( FParentForm->Handle, WS_CAPTION );
AddWindowStyle( FParentForm->Handle, WS_BORDER );
FParentForm->Color = clGreen; //For test
}
else
FParentForm->Color = clRed; //For test
}
Regards
Patrick
 

Re:Component constructor seems not to executed Why ?

"Patrick Faure" < XXXX@XXXXX.COM >wrote in message
Quote
__fastcall TADiAppBar(TADiComponent* Owner);
Your constructor is wrong. It must take a TComponent parameter.
Quote
FParentForm = (TForm*) Owner;
That is not safe. The Owner may not always be a TForm to begin with. You
should be using a dynamic_cast<>instead, which performs a validation that
the source pointer is actually what you need it to be. If the cast fails,
NULL is returned, ie:
FParentForm = dynamic_cast<TForm*>(Owner);
Quote
// TForm only owner ancestor type
if( !Owner->InheritsFrom( __classid( TForm ) ) )
You don't need to do that. By doing the dynamic_cast in TADiComponent's
constructor, your TADiAppBar constructor can then just check if the
ParentForm property in assigned or not.
// TForm only owner ancestor type
if( !ParentForm )
throw Exception( LoadStr( ERROR001 ) );
Quote
// Only one ADiAppBar component
for( int i = 0; i < FParentForm->ComponentCount ; ++ i )
if( ( FParentForm->Components[i]->InheritsFrom( __classid(
TADiAppBar ) )
&&
( FParentForm->Components[i] != this ) ) )
throw Exception( LoadStr( ERROR003 ) );
Again, use dynamic_cast instead of InheritsFrom(), and also for better
performance, check for 'this' before performing the cast:
// Only one ADiAppBar component
for( int i = 0; i < FParentForm->ComponentCount ; ++ i )
{
if( FParentForm->Components[i] != this )
{
if( dynamic_cast<TADiAppBar*>(FParentForm->Components[i]) !=
NULL )
throw Exception( LoadStr( ERROR003 ) );
}
}
Quote
RemoveWindowStyle( FParentForm->Handle, WS_CAPTION );

AddWindowStyle( FParentForm->Handle, WS_BORDER );
FParentForm->Color = clGreen; //For test
The main problem with doing that is your settings may not be persistent. As
soon as the form recreates its window handle for any reason, your settings
will be lost. The only way to persist window styles across a recreation is
if the custom styles are applied from within the form's overriden
CreateParams() method, which a component cannot override.
What exactly are you trying to accomplish in the first place by messing
around with the form's styles?
Gambit
 

Re:Component constructor seems not to executed Why ?

Thank you for your answers.
Quote
>__fastcall TADiAppBar(TADiComponent* Owner);
Your constructor is wrong. It must take a TComponent parameter.
Ok it works fine thank you, but:
- Why VCL class constructor does always take a TComponent*
Owner parameter and not a descendant of TComponent like
my TADiComponent wich is a descendant of TComponent?
Quote
>RemoveWindowStyle( FParentForm->Handle, WS_CAPTION );
>
>AddWindowStyle( FParentForm->Handle, WS_BORDER );

What exactly are you trying to accomplish in the first place by messing
around with the form's styles?

At run time, I want my component to transform the owner form.
The owner form will become an AppBar.
No caption, but a thin border to detect mouse move and so slide
the AppBar onto the screen when the Appbar is hidden out of the
screen.
Thanks again
Patrick
 

Re:Component constructor seems not to executed Why ?

"Patrick Faure" < XXXX@XXXXX.COM >wrote in message
Quote
- Why VCL class constructor does always take a TComponent*
Owner parameter and not a descendant of TComponent like
my TADiComponent wich is a descendant of TComponent?
Because that is the way polymorphism works. In order to override a virtual
class method, you must use the EXACT same signature as the original virtual
method. TComponent's constructor only knows how to accept another
TComponent as an Owner. All descendant constructors must use the same
constructor signature. If they do not, then the constructor is not properly
overriden, as you already noticed earlier.
Also, Delphi (the language the VCL is actually written in, not C++) has two
features that C++ does not have - constructors can be virtual, and classes
can be instantiated via compiler-generated metadata without needing to know
the actual class types. These features play a major role in the VCL,
especially the DFM streaming system. When streaming components from the DFM
at runtime, the DFM system uses the metadata to create the streamed
component instances, and that requires calling constructors via a base class
pointer. If the signatures of the constructors do not exact match
TComponent's constructor, then the descendant component contructors will not
be executed correctly, and thus the components will not be fully initialized
properly.
Gambit