Board index » cppbuilder » Dialog in main form constructor

Dialog in main form constructor


2006-11-07 10:11:02 AM
cppbuilder71
Here's my problem.
I have a program with several forms. One form is a dialog box that I made
using the Dialog wizard. This sets up an Application->CreateForm instance
for the dialog.
Here is the basic file
Application->Initialize();
Application->CreateForm(__classid(TMIBdownloadForm),
&MIBdownloadForm);
Application->CreateForm(__classid(TadminLoginForm),
&adminLoginForm);
Application->CreateForm(__classid(TpasswordAdminForm),
&passwordAdminForm);
Application->CreateForm(__classid(TverifyErrorForm),
&verifyErrorForm);
Application->CreateForm(__classid(TMIBToolDirectoryDialog),
&MIBToolDirectoryDialog);
Application->Run();
Now when the CreateForm for the main Form (MIBdownloadForm) runs its
constructor calls the MIBToolDirectoryDialog which is not create yet and
gives me an error.
If I move the CreateForm for MIBToolDirectoryDialog ahead of the CreateForm
for the main form MIBdownloadForm then the constructor for main form seems
to work correctly but then evidentily Application->Run thinks the first form
create is the main form which is now the dialog and not the main form. so
the dialog form runs again and closes the app if I close the dialog.
The only way around this I can think of is to remove the dialog from the
project list and make it a member of the main form. Some how this does seem
to be a correct solution and wonder if it will correctly without any hidden
problems.
Is there a better way to do this.
I also do not understand how the application closes. If I try to use the
Close() function in the main form constructor it does not close the app. The
app will still run the other CreateForm statements. This is a problem since
another form uses some dynamic variables that are create and initialized in
the main form constructor. If I cannot create these variables I want to quit
the app but the then the other CreateForm statements run and give me an
error when they try to access the members in the main form.
Note that Application->Terminate() instead of Close() results in the same
behavior.
Any suggestions. I think I can use some boolean state variables and finally
work around the problem but seems like there should be a simplier, more
direct solution.
Bill
 
 

Re:Dialog in main form constructor

I will address a few of your questions directly however my overall
suggestion is for you to leave TMIBdownloadForm as the main form. Add an
OnShow event handler and move the code where you call the dialog from the
constructor into the event handler.
Quote
The only way around this I can think of is to remove the dialog from the
project list and make it a member of the main form. Some how this does
seem to be a correct solution and wonder if it will correctly without any
hidden problems.
In my applications I only have one form auto created and therefore only have
one global variable. All other forms I create as needed. There is nothing
in the VCL that forces you to use the auto-generated global variables,
though you are required to have one form auto-created in order for the
application to know what its main form is.
Quote
Is there a better way to do this.
I wouldn't make the dialog a member of the main form. Rather, I would use a
temporary variable like so:
void __fastcall TMIBdownloadForm::FormShow(TObject *Sender)
{
TMIBToolDirectoryDialog* dialog = new TMIBToolDirectoryDialog(this);
dialog->ShowModal(); // or Execute(), not sure what you are using
delete dialog; // Or use an RAII class or smart pointer instead
}
Quote
I also do not understand how the application closes. If I try to use the
Close() function in the main form constructor it does not close the app.
As you have found Close() will not work in the constructor of any form. To
terminate an application use Application->Terminate(). However, execution
does not terminate immediately and any code that follows the call will be
executed. What you really need is to design your initialization a little
better. Creating the variables in the OnShow event handler will probably
help in this situation. If a variable cannot be created in the OnShow
handler then use Application->Terminate() there. All auto-created forms
will already be constructed before OnShow is called.
- Clayton
 

Re:Dialog in main form constructor

"William Riley" < XXXX@XXXXX.COM >wrote in message
Quote
Here's my problem.
The real problem is that your project is auto-creating more forms then it
should be to begin with. A better design would be to auto-create only the
actual MainForm, and then use 'new' to dynamically allocae the other forms
on an as-needed basis in your own code.
Quote
I have a program with several forms.
That is because your forms have too many dependancies on each other. You
should design your code to separate the data logic from the UI logic. Then
it won't matter as much anymore when the UI forms are created.
Quote
One form is a dialog box that I made using the Dialog wizard. This
sets up an Application->CreateForm instance for the dialog.
Just because the wizard generates default code does not mean that you have
to keep that code.
Quote
If I move the CreateForm for MIBToolDirectoryDialog ahead of the
CreateForm for the main form MIBdownloadForm then the constructor
for main form seems to work correctly but then evidentily Application->Run
thinks the first form create is the main form which is now the dialog and
not the main form.
That is how CreateForm() is specifically designed to work. The first form
instantiated via CreateForm() gets assigned to the TApplication::MainForm
property. The only way to bypass that is to use 'new' instead of
CreateForm() if you need to instantiate any forms before the actual
MainForm.
Quote
The only way around this I can think of is to remove the dialog from
the project list and make it a member of the main form.
That would be fine.
Quote
Some how this does seem to be a correct solution and wonder if it
will correctly without any hidden problems.
That depends on what it actually does, and how much the rest of your code is
dependant on it.
Quote
Is there a better way to do this.
There are much better ways to handle these things. You should seriously
re-think your overall design strategy. You are focusing too much on just
the UI, and not what the UI is trying to accomplish.
Quote
I also do not understand how the application closes.
Yes, you do, because you yourself explained it.
Quote
If I try to use the Close() function in the main form constructor it does
not close the app.
It is not supposed to. You cannot Close() a form while it is still being
created.
Quote
The app will still run the other CreateForm statements.
As it should be. Closing the MainForm does not terminate the application
right away. It merely posts a WM_QUIT message to the message queue, which
is not entered until TApplication::Run() has been called.
Quote
This is a problem since another form uses some dynamic variables
that are create and initialized in the main form constructor.
Again, you should re-think your overall design to better separate your data
from the UI. Then you can initialize/manipulate your data directly without
worying about what the UI does.
Quote
If I cannot create these variables I want to quit the app
All the more reason to separate them from the UI code, so that they can be
initialized by themselves, reducing the overhead involved if something goes
wrong. If they can't be created, then you can simply exit from WinMain()
without creating a single form.
Quote
but the then the other CreateForm statements run and give me an error
when they try to access the members in the main form.
Only because you have not set up your startup code to handle that scenerio
yet.
Quote
Note that Application->Terminate() instead of Close() results in the same
behavior.
As it should be. When the MainForm is closed, it calls Terminate(), which
then posts the WM_QUIT message.
Gambit
 

{smallsort}

Re:Dialog in main form constructor

Thanks for the comments and suggestions from Clayton and Gambit.
Of course this always causes many more questions but hoping you can answer
one quick one.
What causes an OnShow event? My understanding is that it is triggered by
change the control Visible property to true. Thats OK but what I would like
to know is there anything on the system side that will trigger the event
besides the normal Window create, show and draw on start up? There doesn't
appear to be a windows message for this and I couldn't seem to trigger the
OnShow by some common manipulation of the Window.
Is it safe to assume that unless your program directly manipulates the
Visible property the OnShow event will not be triggered once the form is
contructed and drawn on the screen?
If this is the case then what is the purpose of the OnShow event? Is it
specifically meant to allow initialization that should probably not be done
in the constructor?
"William Riley" < XXXX@XXXXX.COM >wrote in message
Quote
Here's my problem.

I have a program with several forms. One form is a dialog box that I made
using the Dialog wizard. This sets up an Application->CreateForm instance
for the dialog.
Here is the basic file
Application->Initialize();
Application->CreateForm(__classid(TMIBdownloadForm),
&MIBdownloadForm);
Application->CreateForm(__classid(TadminLoginForm),
&adminLoginForm);
Application->CreateForm(__classid(TpasswordAdminForm),
&passwordAdminForm);
Application->CreateForm(__classid(TverifyErrorForm),
&verifyErrorForm);

Application->CreateForm(__classid(TMIBToolDirectoryDialog),
&MIBToolDirectoryDialog);
Application->Run();

Now when the CreateForm for the main Form (MIBdownloadForm) runs its
constructor calls the MIBToolDirectoryDialog which is not create yet and
gives me an error.
If I move the CreateForm for MIBToolDirectoryDialog ahead of the
CreateForm for the main form MIBdownloadForm then the constructor for main
form seems to work correctly but then evidentily Application->Run thinks
the first form create is the main form which is now the dialog and not the
main form. so the dialog form runs again and closes the app if I close the
dialog.
The only way around this I can think of is to remove the dialog from the
project list and make it a member of the main form. Some how this does
seem to be a correct solution and wonder if it will correctly without any
hidden problems.
Is there a better way to do this.

I also do not understand how the application closes. If I try to use the
Close() function in the main form constructor it does not close the app.
The app will still run the other CreateForm statements. This is a problem
since another form uses some dynamic variables that are create and
initialized in the main form constructor. If I cannot create these
variables I want to quit the app but the then the other CreateForm
statements run and give me an error when they try to access the members in
the main form.
Note that Application->Terminate() instead of Close() results in the same
behavior.
Any suggestions. I think I can use some boolean state variables and
finally work around the problem but seems like there should be a simplier,
more direct solution.

Bill

 

Re:Dialog in main form constructor

William Riley wrote:
Quote
What causes an OnShow event? My understanding is that it is triggered by
change the control Visible property to true.
Indeed. You can also use the sequence Hide() and Show();
The eventhandler has been named OnShow where it is actually OnBeforeShow.
Quote
... I couldn't seem to trigger the
OnShow by some common manipulation of the Window.
Why would you?
Quote
If this is the case then what is the purpose of the OnShow event?
You could execute some code then (keeping in mind that it is onbeforeshow).
Mostly you would use that in combination with OnHide too then.
You could free memory for instance.
Hans.
 

Re:Dialog in main form constructor

William Riley wrote:
Quote
... the
Visible property the OnShow event will not be triggered once the form is
contructed and drawn on the screen?
Of course the user can close the window with [X]. When it is not destroyed
you can make it Visible again. OnShow() will trigger then.
Hans.
 

Re:Dialog in main form constructor

Quote
What causes an OnShow event? My understanding is that it is triggered by
change the control Visible property to true.
Yes. Or a call to Show().
Quote
I couldn't seem to trigger the OnShow by some common manipulation of the
Window.
I'm assuming by common you mean minimizing, restoring, and other such
operations. The following scenario will cause the OnShow to fire again.
Add a button. In the OnClick handler add this code:
Hide();
Sleep(500);
Show();
When the form is shown again the OnShow event handler will fire. From
reading your post I believe you might already know this, though.
Quote
Is it safe to assume that unless your program directly manipulates the
Visible property the OnShow event will not be triggered once the form is
contructed and drawn on the screen?
I believe so. If you take a look at the source code in Forms.pas you will
see that the only time this event is used is if the form is being shown.
Quote
If this is the case then what is the purpose of the OnShow event?
Its purpose is to perform actions that should happen when the form is made
visible. Your design will dictate when this is appropriate. For instance,
a child form might have some timer that fires every 3 seconds. When the
form is hidden (OnHide) you can turn off that timer. When the form is made
visible again (OnShow) you reenable the timer.
Quote
Is it specifically meant to allow initialization that should probably not
be
done in the constructor?
No. If you never hide your forms then you can use it for initializations
but as you found out if your form can ever be hidden, and therefore shown
again, then the code in the OnShow handler will execute again. One way to
guard against this happening is to add the following code as the first line
of the handler:
OnShow = NULL;
Another way of accomplishing initializations after the form's construction
would be to add a special message and then post that message to the window.
// header file
#define UM_DELAYEDINIT WM_USER + 100
class TMyForm : public TForm
{
...
protected:
void UmDelayedInit(TMessage& Message);
BEGIN_MESSAGE_MAP
VCL_MESSAGE_HANDLER(UM_DELAYEDINIT, TMessage, UmDelayedInit)
END_MESSAGE_MAP(TForm)
...
};
// cpp file
void __fastcall TMyForm::TMyForm(TComponent* AOwner) : TForm(AOwner)
{
// some initializations
PostMessage(Handle, UM_DELAYEDINIT, 0, 0);
}
void TMyForm::UmDelayedInit(TMessage& Message)
{
// other initializations
// Call Application->Terminate() if necessary
}
I hope this helps a little bit. For simplicity sake I would choose the
first method but be sure to comment the intent of the code in the event
handler.
- Clayton
 

Re:Dialog in main form constructor

"William Riley" < XXXX@XXXXX.COM >wrote in message
Quote
What causes an OnShow event?
OnShow is triggered whenever the form receives a CM_SHOWINGCHANGED message
while the Showing property is True.
Quote
My understanding is that it is triggered by change the control
Visible property to true.
That is one possible trigger. There are others.
Quote
what I would like to know is there anything on the system side that will
trigger the event besides the normal Window create, show and draw on start
up?
OnShow is strictly a VCL-managed event only. It is not an OS-driven event.
Quote
There doesn't appear to be a windows message for this
There is not.
Quote
I couldn't seem to trigger the OnShow by some common manipulation
of the Window.
Why are you trying to trigger it manually?
Quote
Is it safe to assume that unless your program directly manipulates the
Visible property the OnShow event will not be triggered once the form
is contructed and drawn on the screen?
Generally, yes.
Quote
If this is the case then what is the purpose of the OnShow event?
Exactly what the documentation says it is for:
"Occurs when the form is shown (that is, when its Visible property is
set to true)."
Quote
Is it specifically meant to allow initialization that should probably not
be done in the constructor?
That is one common use for it, but that is not what it is solely designed
for. There are other ways to accomplish the same thing.
Gambit
 

Re:Dialog in main form constructor

Thanks everyone for you comments and responses. I appreciate the time you
take for this. So far this is the only real source I have found for answers
to questions about BCB.
"William Riley" < XXXX@XXXXX.COM >wrote in message
Quote
Thanks for the comments and suggestions from Clayton and Gambit.
Of course this always causes many more questions but hoping you can answer
one quick one.
What causes an OnShow event? My understanding is that it is triggered by
change the control Visible property to true. Thats OK but what I would
like to know is there anything on the system side that will trigger the
event besides the normal Window create, show and draw on start up? There
doesn't appear to be a windows message for this and I couldn't seem to
trigger the OnShow by some common manipulation of the Window.
Is it safe to assume that unless your program directly manipulates the
Visible property the OnShow event will not be triggered once the form is
contructed and drawn on the screen?
If this is the case then what is the purpose of the OnShow event? Is it
specifically meant to allow initialization that should probably not be
done in the constructor?

"William Riley" < XXXX@XXXXX.COM >wrote in message
news:454feb31$ XXXX@XXXXX.COM ...
>Here's my problem.
>
>I have a program with several forms. One form is a dialog box that I made
>using the Dialog wizard. This sets up an Application->CreateForm instance
>for the dialog.
>Here is the basic file
>Application->Initialize();
>Application->CreateForm(__classid(TMIBdownloadForm),
>&MIBdownloadForm);
>Application->CreateForm(__classid(TadminLoginForm),
>&adminLoginForm);
>Application->CreateForm(__classid(TpasswordAdminForm),
>&passwordAdminForm);
>Application->CreateForm(__classid(TverifyErrorForm),
>&verifyErrorForm);
>
>Application->CreateForm(__classid(TMIBToolDirectoryDialog),
>&MIBToolDirectoryDialog);
>Application->Run();
>
>Now when the CreateForm for the main Form (MIBdownloadForm) runs its
>constructor calls the MIBToolDirectoryDialog which is not create yet and
>gives me an error.
>If I move the CreateForm for MIBToolDirectoryDialog ahead of the
>CreateForm for the main form MIBdownloadForm then the constructor for
>main form seems to work correctly but then evidentily Application->Run
>thinks the first form create is the main form which is now the dialog and
>not the main form. so the dialog form runs again and closes the app if I
>close the dialog.
>The only way around this I can think of is to remove the dialog from the
>project list and make it a member of the main form. Some how this does
>seem to be a correct solution and wonder if it will correctly without any
>hidden problems.
>Is there a better way to do this.
>
>I also do not understand how the application closes. If I try to use the
>Close() function in the main form constructor it does not close the app.
>The app will still run the other CreateForm statements. This is a problem
>since another form uses some dynamic variables that are create and
>initialized in the main form constructor. If I cannot create these
>variables I want to quit the app but the then the other CreateForm
>statements run and give me an error when they try to access the members
>in the main form.
>Note that Application->Terminate() instead of Close() results in the same
>behavior.
>Any suggestions. I think I can use some boolean state variables and
>finally work around the problem but seems like there should be a
>simplier, more direct solution.
>
>Bill
>


 

Re:Dialog in main form constructor

William Riley wrote:
Quote
... I appreciate the time you
take for this.
"William Riley" < XXXX@XXXXX.COM >wrote in message
news:455223ea$ XXXX@XXXXX.COM ...

>Thanks for the comments and suggestions from Clayton and Gambit.
....
>"William Riley" < XXXX@XXXXX.COM >wrote in message
>news:454feb31$ XXXX@XXXXX.COM ...
>
>>Here's my problem.
Please take the time to remove your quotes. You are quoting yourself twice
here. Makes no sence. Who should read that all?
Hans.
 

Re:Dialog in main form constructor

"William Riley" < XXXX@XXXXX.COM >wrote:
Quote

Hans is quite correct. Please trim your posts.
Quote
[...] So far this is the only real source I have found for
answers to questions about BCB.
Be aware that everything that is posted in these groups gets
archived and you have complete access to the archives.
search Borland archives:
www.tamaracka.com/search.htm
search multiple groups from all over:
groups.google.com/
search one specific group:
groups.google.com/advanced_group_search
~ JD