Board index » cppbuilder » Opening modal dialog immediately application starts

Opening modal dialog immediately application starts


2006-12-04 10:14:11 PM
cppbuilder71
Hi,
I need to display a modal dialog box as soon as my main form has been fully
displayed for the first time. I tried using ShowModal when the main form's
OnShow event first occurs (within FormShow) but this is too early - the main
form isn't yet displayed. Also tried it in response to OnActivate but still
too early - the form isn't yet at it's final size.
Is there anything after OnShow or OnActivate that I can use as an indication
that now is a good time to display a modal dialog box?
TIA,
Geordie
 
 

Re:Opening modal dialog immediately application starts

newsgroups.borland.com wrote:
Quote
Is there anything after OnShow or OnActivate that I can use as an indication
that now is a good time to display a modal dialog box?
There are several ways.
One of them is to Enable a TTimer as last statement in the constructor.
In the TTimer eventhandler display the modal dialog.
Hans.
 

Re:Opening modal dialog immediately application starts

Assuming your main form is named Form1, the modal form Form2, and the
project Project1, modify the Project1.cpp file such that:
Application->Initialize();
Application->CreateForm(__classid(TForm1), &Form1);
Application->CreateForm(__classid(TForm2), &Form2);
Form1->Show();
Form2->ShowModal();
Application->Run();
Don't forget to include the header of Form1 and Form2.
- Erol
On Dec 5, 12:10 am, Hans Galema < XXXX@XXXXX.COM >wrote:
Quote
newsgroups.borland.com wrote:
>Is there anything after OnShow or OnActivate that I can use as an indication
>that now is a good time to display a modal dialog box?There are several ways.

One of them is to Enable a TTimer as last statement in the constructor.

In the TTimer eventhandler display the modal dialog.

Hans.
 

{smallsort}

Re:Opening modal dialog immediately application starts

Hi,
Thanks both for the ideas.
Hans - I'd prefer not to use a timer for this task if I can avoid it - if
the delay is set too short (or someting in the system causes latency) then
the scheme fails, and if it's too long the user encounters a pause.
Erol - I like your idea of using direct control of the start-up sequence in
the project file, and may end up doing it that way. Changing the project
file is something that I doo with caution because I don't know enough about
what goes on behind the scenes, but it's not difficult to see what's going
on here. Out of interest - where is the initial call to Form1->Show() in a
normal project?
In the meantime, I've got around it by adding an ApplicationEvents object to
Form1 and calling Form2->ShowModal the first time an OnIdle event occurs.
Slightly messy, but seems to work ok.
Thanks again,
Geordie
"Erol Fornoles" < XXXX@XXXXX.COM >wrote in message
Quote
Assuming your main form is named Form1, the modal form Form2, and the
project Project1, modify the Project1.cpp file such that:

Application->Initialize();
Application->CreateForm(__classid(TForm1), &Form1);
Application->CreateForm(__classid(TForm2), &Form2);

Form1->Show();
Form2->ShowModal();

Application->Run();

Don't forget to include the header of Form1 and Form2.

- Erol

On Dec 5, 12:10 am, Hans Galema < XXXX@XXXXX.COM >wrote:
>newsgroups.borland.com wrote:
>>Is there anything after OnShow or OnActivate that I can use as an
>>indication
>>that now is a good time to display a modal dialog box?There are several
>>ways.
>
>One of them is to Enable a TTimer as last statement in the constructor.
>
>In the TTimer eventhandler display the modal dialog.
>
>Hans.

 

Re:Opening modal dialog immediately application starts

Geordie wrote:
Quote
Hans - I'd prefer not to use a timer for this task if I can avoid it - if
the delay is set too short (or someting in the system causes latency) then
the scheme fails, and if it's too long the user encounters a pause.
You can set it to 1 ms (the shortest interval) and it will not fail.
Did you try?
Hans.
 

Re:Opening modal dialog immediately application starts

Hans Galema < XXXX@XXXXX.COM >wrote:
Quote

You can set it to 1 ms (the shortest interval) and it will
not fail.
That's because the timer is message based and messages
don't start to get processed until after the form is fully
constructed and then it still has to wait until all of the
other pending messages get processed.
One can accomplish the exact same thing by posting a custom
message to the form's Handle as the last statement in the ctor
but then you'd also need to add a message handler to process
the custom message.
Quote
Did you try?
Even though it accomplishes the same thing in the same way
and it's easier to code for, there's just something about
using a timer ... <shudder>... so I doubt it.
~ JD
 

Re:Opening modal dialog immediately application starts

Geordie wrote:
Quote
...Changing the project
file is something that I doo with caution because I don't know enough about
what goes on behind the scenes, but it's not difficult to see what's going
on here.
It works. But as soon as you add a new form to the project or remove
one from the project that added code will be gone.
You have to add it again then. Which you likely will forget.
Hans.
 

Re:Opening modal dialog immediately application starts

JD wrote:
Quote
Even though it accomplishes the same thing in the same way
and it's easier to code for, there's just something about
using a timer ... <shudder>...
What is it that makes you shudder for a simple, elegant and rockproof
solution?
Hans.
 

Re:Opening modal dialog immediately application starts

"JD" < XXXX@XXXXX.COM >wrote in message
Quote

Hans Galema < XXXX@XXXXX.COM >wrote:
>
>You can set it to 1 ms (the shortest interval) and it will
>not fail.

That's because the timer is message based and messages
don't start to get processed until after the form is fully
constructed and then it still has to wait until all of the
other pending messages get processed.

One can accomplish the exact same thing by posting a custom
message to the form's Handle as the last statement in the ctor
but then you'd also need to add a message handler to process
the custom message.

>Did you try?

Even though it accomplishes the same thing in the same way
and it's easier to code for, there's just something about
using a timer ... <shudder>... so I doubt it.

~ JD

Hans - Thanks for not letting me get away so lightly - I hadn't appreciated
the significance of enabling the timer as the last thing in the ctor code.
I have now tried it with a 1ms timer and agree that it works well.
JD - Thanks for the explaining how, being based on a received message, it's
safe to rely on a timer or sent message at the end of the main form's ctor.
I'm quite happy with that now. I haven't yet tried it with a simple
message.
Regards,
Geordie
 

Re:Opening modal dialog immediately application starts

"Hans Galema" < XXXX@XXXXX.COM >wrote in message
Quote
Geordie wrote:

>...Changing the project file is something that I doo with caution because
>I don't know enough about what goes on behind the scenes, but it's not
>difficult to see what's going on here.

It works. But as soon as you add a new form to the project or remove
one from the project that added code will be gone.

You have to add it again then. Which you likely will forget.

Hans.
I tried it out - interesting ...
If I put
Form1->Show();
Form2->ShowModal();
after the final Application->CreateForm call, it seems safe. I can add /
remove other forms to / from the project without problems.
If, however, I already have a Form3 and I add my code between the Form2 and
Form3 CreateForm calls, then I lose my code if I remove Form3 from the
project.
This is with BCB6, but I guess I have no way of knowing whether other
versions will behave the same. I still like the approach, but I'm more wary
now.
Regards,
Geordie
 

Re:Opening modal dialog immediately application starts

"Geordie" <x>wrote:
Quote

[...] it's safe to rely on a timer or sent message at the
end of the main form's ctor.
To be clear, neither need to be at the end of the ctor because
that block of code will execute 'till completion before any
messages get processed. It just makes sense to put it there.
Additionally, you need to make a destinction between sending
and posting a message. SendMessage is blocking. IOW, if you
use SendMessage, execution is halted until the message has
been processed and control returns to the next statement. By
contrast, PostMessage adds the message to the end of the
message que to be processed later and execution continues to
the next statement. The que is only pumped for messages when
the application is not executing code.
The point in time when the timer executes and the custom
message is processed and the TApplication::OnIdle event is
fired is all the same but I prefer using the custom message
only in this case.
The user could defeat OnIdle by moving the mouse and keeping
the application busy and possibly click something before OnIdle
executes and since OnIdle repeatedly executes, you need to add
some sort of flag and since OnIdle executes litterally millions
of times ..... well that's alot of nothing that doesn't have
to happen.
As for the TTimer (besides my own issues with timers) it
seems to me to be a sort of kludge or hack in this case
because it's use is counter-intuitive. Certainly, it does
the job but not how one might expect. Generally, one thinks
of timing when using a timer but there is no way to time the
process that you're interested in.
The only reason the timer works in this case is because
of the internals of the OS. That being the case, I would
prefere to use code that clearly demonstrates my intent.
Quote
I haven't yet tried it with a simple message.
First, you need to define the message:
//-------------------------------------------------------------
#define UWM_INITIALIZED (WM_USER + 100)
//-------------------------------------------------------------
class TForm1 : public TForm
{
....
};
//-------------------------------------------------------------
Then you need to add a way to catch the message. You can add a
message map *or* you can override the WndProc method. To add a
message map:
//-------------------------------------------------------------
#define UWM_INITIALIZED (WM_USER + 100)
//-------------------------------------------------------------
class TForm1 : public TForm
{
private:
MESSAGE void __fastcall UWMInitialized( TMessage &Message );
public:
BEGIN_MESSAGE_MAP
VCL_MESSAGE_HANDLER( UWM_INITIALIZED, TMessage, UWMInitialized )
END_MESSAGE_MAP( TForm )
};
//-------------------------------------------------------------
//-------------------------------------------------------------
MESSAGE void __fastcall TForm1::UWMInitialized( TMessage &Message )
{
// your code goes here
}
//-------------------------------------------------------------
To override the WndProc method:
//-------------------------------------------------------------
#define UWM_INITIALIZED (WM_USER + 100)
//-------------------------------------------------------------
class TForm1 : public TForm
{
typedef TForm inherited;
protected:
virtual void __fastcall WndProc( TMessage &Message );
};
//-------------------------------------------------------------
//-------------------------------------------------------------
void __fastcall TForm1::WndProc( TMessage &Message )
{
if( Message.Msg == UWM_INITIALIZED )
{
// your code goes here
}
inherited::WndProc( Message );
}
//-------------------------------------------------------------
Usage:
::PostMessage( Handle, UWM_INITIALIZED, 0, 0 );
~ JD
 

Re:Opening modal dialog immediately application starts

Hans Galema < XXXX@XXXXX.COM >wrote:
Quote

What is it that makes you shudder for a simple, elegant and
rockproof solution?
It's not elegant. To the contrary, it's counter-intuitive
because one expects a timer to work based on time. In reality,
the timer fails to execute in a timely manner but it works
because of the particulars of program start-up. It just seems
like a hack to me.
~ JD
 

Re:Opening modal dialog immediately application starts

JD wrote:
Quote
It's not elegant. To the contrary, it's counter-intuitive
because one expects a timer to work based on time. In reality,
the timer fails to execute in a timely manner
Now I see what you mean.
But then I have no problems with that as I can use it
to full advantage.
It is not the time aspect but the 'do this as soon as you're done'.
Hans.
 

Re:Opening modal dialog immediately application starts

I use this code in the OnActivate event for the main form and have had no
problems:
void __fastcall TfmMain::FormActivate(TObject *Sender)
{
OnActivate = NULL; // Only show the logon the first time (when the appl
starts)
TfmLogon* logon = new TfmLogon(Application);
if (logon->ShowModal() == mrOk) {
....
- Kevin
"newsgroups.borland.com" <x>wrote in message
Quote
Hi,

I need to display a modal dialog box as soon as my main form has been
fully displayed for the first time. I tried using ShowModal when the main
form's OnShow event first occurs (within FormShow) but this is too early -
the main form isn't yet displayed. Also tried it in response to
OnActivate but still too early - the form isn't yet at it's final size.

Is there anything after OnShow or OnActivate that I can use as an
indication that now is a good time to display a modal dialog box?

TIA,
Geordie

 

Re:Opening modal dialog immediately application starts

"JD" < XXXX@XXXXX.COM >wrote in message
Quote

"Geordie" <x>wrote:
>
>[...] it's safe to rely on a timer or sent message at the
>end of the main form's ctor.

To be clear, neither need to be at the end of the ctor because
that block of code will execute 'till completion before any
messages get processed. It just makes sense to put it there.
Thanks - understood.

Additionally, you need to make a destinction between sending
and posting a message. SendMessage is blocking. IOW, if you
use SendMessage, execution is halted until the message has
been processed and control returns to the next statement. By
contrast, PostMessage adds the message to the end of the
message que to be processed later and execution continues to
the next statement. The que is only pumped for messages when
the application is not executing code.
Point well made - sloppy writing on my part, I'm afraid. Have used both
PostMessage and SendMessage in the past and (hopefully) wouldn't have got it
wrong in the actual code!
Quote

The point in time when the timer executes and the custom
message is processed and the TApplication::OnIdle event is
fired is all the same but I prefer using the custom message
only in this case.

The user could defeat OnIdle by moving the mouse and keeping
the application busy and possibly click something before OnIdle
executes and since OnIdle repeatedly executes, you need to add
some sort of flag and since OnIdle executes litterally millions
of times ..... well that's alot of nothing that doesn't have
to happen.
I was ok on using a static variable to ensure the section only fired once,
but never truly happy with using OnIdle because I wasn't 'really' waiting
for the app to become idle - similar to your misgivings about using a timer.
And, yes, it doesn't seem right to use only one OnIdle call out of millions.
Quote

As for the TTimer (besides my own issues with timers) it
seems to me to be a sort of kludge or hack in this case
because it's use is counter-intuitive. Certainly, it does
the job but not how one might expect. Generally, one thinks
of timing when using a timer but there is no way to time the
process that you're interested in.

The only reason the timer works in this case is because
of the internals of the OS. That being the case, I would
prefere to use code that clearly demonstrates my intent.

>I haven't yet tried it with a simple message.

First, you need to define the message:
Supplying sample code was very generous - more than I was expecting, and
saved me a bit of work. All working like a dream now.
Thanks,
Geordie