Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: VCL app creation part


This question is answered. Helpful answers available: 2. Correct answers available: 1.


Permlink Replies: 7 - Last Post: Aug 23, 2017 1:21 PM Last Post By: Remy Lebeau (Te... Threads: [ Previous | Next ]
Goran Ekstrom

Posts: 149
Registered: 1/10/04
VCL app creation part  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Aug 17, 2017 4:27 PM
Hi,
what is "legal" to do between the:

Application->Initialize();
Application->CreateForm(__classid(TMainForm), &MainForm);

and..

Application->Run();

part?

For reasons rooted in the Win9x days I made my own Messagbox VCL form many years ago that I in the MainForm creator create dynamically. Later during the MainForm creator I make some checks and if any problems are found I modally display a message using that custom VCL MessageBox form, i.e. before the complete app is created and the Application->Run(); has executed.

The problem is that now with Tokyo I am getting an intermittent "Cannot Make A Visible Window Modal" error message, seems to be som race condition. After replacing my messagebox call with Application->MessageBox I cannot reproduce the error anymore.

Regards
Goran
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: VCL app creation part [Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Aug 17, 2017 9:09 PM   in response to: Goran Ekstrom in response to: Goran Ekstrom
Goran Ekstrom wrote:

what is "legal" to do between the:

Application->Initialize();
Application->CreateForm(__classid(TMainForm), &MainForm);

and..

Application->Run();

part?

You can do whatever you want. It is all just standard C++ code,
afterall.

Just know that the IDE "owns" the main project source file and will
automatically remove any code that is between these Aplication calls,
so be prepared to restore any custom code on each save/compile of the
project. I prefer to keep the main source file read-only when I'm not
actively working on it, to prevent exactly this behavior.

For reasons rooted in the Win9x days I made my own Messagbox VCL form
many years ago that I in the MainForm creator create dynamically.
Later during the MainForm creator I make some checks and if any
problems are found I modally display a message using that custom VCL
MessageBox form, i.e. before the complete app is created and the
Application->Run(); has executed.

Why not just dynamically create the Form on an as-needed basis, instead
of once at started?

The problem is that now with Tokyo I am getting an intermittent
"Cannot Make A Visible Window Modal" error message, seems to be som
race condition.

You need to use the debugger to figure it out. Perhaps your modal Form
is dependant on the MainForm window being available when it is not
actually. Who knows. Only the debugger can tell you for sure.

After replacing my messagebox call with Application->MessageBox I
cannot reproduce the error anymore.

In VCL, Application->MessageBox() is just a wrapper for the Win32 API
MessageBox() function, using the currently active Form window, or the
Application window if no active Form, as the owner window for the
messagebox dialog.

--
Remy Lebeau (TeamB)
Goran Ekstrom

Posts: 149
Registered: 1/10/04
Re: VCL app creation part [Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Aug 18, 2017 12:22 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
You can do whatever you want. It is all just standard C++ code,
afterall.

I was wondering if VCL was in some incomplete state before the Application->Run(); statement that caused the problem.

Just know that the IDE "owns" the main project source file and will
automatically remove any code that is between these Aplication calls...

I know, none of my code there, it all happens in the MainForm's Creator.

Why not just dynamically create the Form on an as-needed basis, instead
of once at started?

There are between 50-100 uses of a MessageBox so it's tedious. Sure I could place it in a function but...

You need to use the debugger to figure it out. Perhaps your modal Form
is dependant on the MainForm window being available when it is not
actually. Who knows. Only the debugger can tell you for sure.

I tried to but after 10-15 app restarts in the IDE without the error I gave up.

In VCL, Application->MessageBox() is just a wrapper for the Win32 API
MessageBox() function, using the currently active Form window, or the
Application window if no active Form, as the owner window for the
messagebox dialog.

The original reason for me to replace the Application->MessageBox() many years ago was that back in the Win9x/BCB5 days, calling it caused the app to "hang", i.e. the forms all froze as long as the messagebox was active. This seems to not be the case anymore so I'll probably switch to Application->MessageBox() now.

Regards
Goran
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: VCL app creation part [Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Aug 18, 2017 12:58 PM   in response to: Goran Ekstrom in response to: Goran Ekstrom
Goran Ekstrom wrote:

I was wondering if VCL was in some incomplete state before the
Application->Run(); statement that caused the problem.

No, it is not.

Why not just dynamically create the Form on an as-needed basis,
instead of once at started?

There are between 50-100 uses of a MessageBox so it's tedious. Sure I
could place it in a function but...

Which you should. Even a static method of the MessageBox Form class
would suffice.

The original reason for me to replace the Application->MessageBox()
many years ago was that back in the Win9x/BCB5 days, calling it
caused the app to "hang", i.e. the forms all froze as long as the
messagebox was active.

I have been using C++Builder since BCB4 and have NEVER experienced
hangs when using Application->MessageBox(). On the other hand, it does
disable any active Forms (via Forms::DisableTaskWindows()) while the
dialog is open, and then re-enables them (via
Forms::EnableTaskWindows()) when the dialog is closed. It has always
done this (even to this day), that is part of its design.

--
Remy Lebeau (TeamB)
Goran Ekstrom

Posts: 149
Registered: 1/10/04
Re: VCL app creation part [Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Aug 20, 2017 2:19 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
I have been using C++Builder since BCB4 and have NEVER experienced
hangs when using Application->MessageBox(). On the other hand, it does
disable any active Forms (via Forms::DisableTaskWindows()) while the
dialog is open...

That was my original issue, that the GUI "freezez" including windows messaging.
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: VCL app creation part [Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Aug 21, 2017 11:04 AM   in response to: Goran Ekstrom in response to: Goran Ekstrom
Goran Ekstrom wrote:

That was my original issue, that the GUI "freezez" including windows
messaging.

When TApplication::MessageBox() disables active windows, it does not
stop messaging from happening in general. In fact, the Win32 API
MessageBox() runs its own messaging loop (since the main message loop
is blocked). The only thing that should be "frozen" is the user's
ability to interact with other windows behind the messagebox dialog
window, but messages sent to any HWND in the app via
(Post|Send)Message(), or generated via (Peek|Get)Message() will still
work fine. However, messages posted with PostThreadMessage() will not
work, because the message loop inside of MessageBox() ignores thread
messages.

--
Remy Lebeau (TeamB)
Goran Ekstrom

Posts: 149
Registered: 1/10/04
Re: VCL app creation part [Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Aug 23, 2017 6:53 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
... The only thing that should be "frozen" is the user's
ability to interact with other windows behind the messagebox dialog
window, but messages sent to any HWND in the app via
(Post|Send)Message(), or generated via (Peek|Get)Message() will still
work fine...

Tested:

void __fastcall TMainForm::OurMessageHandler(tagMSG &Msg, bool &Handled)

Application->OnMessage = OurMessageHandler;

PostMessage(Application->Handle, OWM__TEST, 0, 0);
or
PostMessage(MainForm->Handle, OWM__TEST, 0, 0);

from a thread and with both the messages stops being received, i.e. the OurMessageHandler event is never fired when Application->MessageBox is shown. This situation is also possible to create simply by pressing the ALT key once.

Also tested:

void __fastcall TMainForm::SubClassWndProc(TMessage &Message)

MainForm->WindowProc = SubClassWndProc;

PostMessage(MainForm->Handle, OWM__TEST, 0, 0);

and here it works, messages still keep coming even if an Application->MessageBox is shown or ALT key is pressed.

Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: VCL app creation part [Edit] [Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Aug 23, 2017 1:21 PM   in response to: Goran Ekstrom in response to: Goran Ekstrom
Goran Ekstrom wrote:

Application->OnMessage = OurMessageHandler;

PostMessage(Application->Handle, OWM__TEST, 0, 0);
or
PostMessage(MainForm->Handle, OWM__TEST, 0, 0);

from a thread and with both the messages stops being received

i.e. the OurMessageHandler event is never fired when
Application->MessageBox is shown.

That is correct.

The TApplication::OnMessage event is fired only when the VCL is the one
retreiving and dispatching messages posted to the message queue. When
a non-VCL modal dialog is active, the VCL message loop is blocked, the
Win32 API (or whatever framework is displaying the dialog) is running
its own message loop that is retreiving and dispatching messages from
the message queue. It knows nothing about the VCL, so that is why the
OnMessage event is not fired.

If you use a VCL modal dialog instead (ShowMessage(), etc), it uses a
modal VCL TForm, so it runs a VCL message loop, and thus fires the
OnMessage event for posted messages.

To receive posted messages even while a non-VCL modal mesage loop is
running, you have to process the messages in the target window's
message procedure instead, which receives messages when they are
dispatched to the window (OnMessage is fired before dispatching). That
means using TApplication::HookMainWindow() for messages posted/sent to
the TApplication window, and overriding the TForm::WndProc() method (or
assigning the TForm::WindowProc property) for messages posted/sent to a
TForm window.

This situation is also possible to create simply by pressing the ALT
key once.

Because again, the VCL message loop is blocked during that time, a
Win32 modal menu message loop is running instead.

MainForm->WindowProc = SubClassWndProc;

PostMessage(MainForm->Handle, OWM__TEST, 0, 0);

and here it works, messages still keep coming even if an
Application->MessageBox is shown or ALT key is pressed.

Yes, the posted messages retreived from the message queue are being
dispatched to the target window by the modal message loop (even though
it is not a VCL message loop), and a window's message procedure is
called during dispatching. The OnMessage event is not.

--
Remy Lebeau (TeamB)
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02