| View previous topic :: View next topic |
| Author |
Message |
JD Guest
|
Posted: Fri Jul 02, 2004 9:17 pm Post subject: One TMyComponent per project |
|
|
I'd like to be able to code the component's constructor to
automatically check if it's the only instance of it's class in
the project when it's dropped on the form. If it isn't, I want
it to say something and then delete itself. I'd also like to
force it to be dropped on the main form if possible.
~ JD
|
|
| Back to top |
|
 |
Remy Lebeau (TeamB) Guest
|
Posted: Fri Jul 02, 2004 10:57 pm Post subject: Re: One TMyComponent per project |
|
|
"JD" <nospam (AT) nospam (DOT) com> wrote
| Quote: | I'd like to be able to code the component's constructor
to automatically check if it's the only instance of it's class
in the project when it's dropped on the form.
|
The easiest way to do that is with a global pointer that is assigned to the
first instance of your component. Then additional instances can check to
see if the pointer is already assigned or not. For example:
--- MyComponent.cpp ---
TMyComponent *Instance = NULL;
__fastcall TMyComponent::TMyComponent(TComponent *Owner)
: TMyBase(Owner)
{
if( Instance )
throw Exception("Only one instance can be created at a time!");
Instance = this;
}
__fastcall TMyComponent::~TMyComponent()
{
Instance = NULL;
}
| Quote: | If it isn't, I want it to say something and then delete itself.
|
Simply throw an exception, as shown above. Everything else will be handled
for you.
| Quote: | I'd also like to force it to be dropped on the main form if possible.
|
That, on the other hand, is a little harder to manage. In the constructor,
the only thing you have access to regarding the creator of the component
instance is the Owner parameter. When you drop a component onto a form, the
form is assigned as the Owner, so you could do the following:
__fastcall TMyComponent::TMyComponent(TComponent *Owner)
: TMyBase(Owner)
{
if( Instance )
throw Exception("Only one instance can be created at a time!");
if( Owner )
{
if( GetParentForm(Owner) != Application->MainForm )
throw Exception("Can only be placed on the MainForm!");
}
Instance = this;
}
The trouble comes when the component is being instantiated dynamically at
runtime. The calling code would be able to specify any Owner it wants to,
which may not be the MainForm at all. And you can't use the Parent property
to decide because the Parent has not been assigned yet while you are still
inside the constructor.
Gambit
|
|
| Back to top |
|
 |
JD Guest
|
Posted: Sat Jul 03, 2004 6:34 am Post subject: Re: One TMyComponent per project |
|
|
"Remy Lebeau (TeamB)" <gambit47.no.spam (AT) no (DOT) spam.yahoo.com> wrote:
| Quote: | [...] Simply throw an exception, as shown above. Everything
else will be handled for you.
|
That's easy enough.
| Quote: | I'd also like to force it to be dropped on the main form if possible.
[...] When you drop a component onto a form, the form is
assigned as the Owner, [...] The trouble comes when the
component is being instantiated dynamically at runtime.
|
Your sample gave me the idea that I could use dynamic_cast
to test the Owner as a TForm prior to testing if it's the main
form:
if( !dynamic_cast<TForm*>(Owner) )
{
// then we know for sure that it's being dynamically allocated
throw Exception("You must assign the MainForm as the Owner.");
}
if( GetParentForm(Owner) != Application->MainForm )
{
// can't tell if it's dynamically allocated
throw Exception("Can only be placed on the MainForm!");
}
Knowing if it's dynamically allocated or not is only important
in as much as providing an exact reason for throwing. I'll just
have to settle for a more generic message:
if( !dynamic_cast<TForm*>(Owner) || GetParentForm(Owner) != Application->MainForm )
{
throw Exception("The Owner must be the MainForm!");
}
Thanks.
~ JD
|
|
| Back to top |
|
 |
Remy Lebeau (TeamB) Guest
|
Posted: Sat Jul 03, 2004 8:31 am Post subject: Re: One TMyComponent per project |
|
|
"JD" <nospam (AT) nospam (DOT) com> wrote
| Quote: | Your sample gave me the idea that I could use
dynamic_cast to test the Owner as a TForm prior
to testing if it's the main form:
|
The only problem with that code is that GetParentForm() does not validate
whether the specified component is NULL, or whether it is already a form.
It always looks at the component's Parent immediately. Thus, your code
logic should be more like the following instead:
TCustomForm *form = NULL;
if( Owner )
{
form = dynamic_cast<TCustomForm*>(Owner);
if( !form )
form = GetParentForm(Owner);
}
if( (!form) || (form != Application->MainForm) )
throw Exception("You must assign the MainForm as the Owner.");
Gambit
|
|
| Back to top |
|
 |
JD Guest
|
Posted: Sat Jul 03, 2004 10:05 am Post subject: Re: One TMyComponent per project |
|
|
"Remy Lebeau (TeamB)" <gambit47.no.spam (AT) no (DOT) spam.yahoo.com> wrote:
| Quote: | [...] Thus, your code logic should be more like the
following instead:
|
I'm too tired right now to understand what was wrong with my
code. I'll have to look at it later but thanks for the sample.
~ JD
|
|
| Back to top |
|
 |
Michael Harris Guest
|
Posted: Sat Jul 03, 2004 12:53 pm Post subject: Re: One TMyComponent per project |
|
|
Hard code the component name property afterconstruction ?
"JD" <nospam (AT) nospam (DOT) com> wrote
| Quote: |
I'd like to be able to code the component's constructor to
automatically check if it's the only instance of it's class in
the project when it's dropped on the form. If it isn't, I want
it to say something and then delete itself. I'd also like to
force it to be dropped on the main form if possible.
~ JD
|
|
|
| Back to top |
|
 |
Remy Lebeau (TeamB) Guest
|
Posted: Sat Jul 03, 2004 9:33 pm Post subject: Re: One TMyComponent per project |
|
|
"JD" <nospam (AT) nospam (DOT) com> wrote
| Quote: | I'm too tired right now to understand what
was wrong with my code.
|
Ignore it. My mistake, I misread how GetParentForm() works, and thought
that it does not check the specified Control itself to see if it is a form.
It actually does, so your earlier code is fine, although I would suggest
getting rid of dynamic_cast:
if( !Owner )
throw Exception("You must assign an Owner.");
if( GetParentForm(Owner) != Application->MainForm )
throw Exception("Can only be placed on the MainForm!");
Gambit
|
|
| Back to top |
|
 |
|