Watch, Follow, &
Connect with Us

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


Welcome, Guest
Guest Settings
Help

Thread: Closing application on startup


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


Permlink Replies: 2 - Last Post: Apr 4, 2016 12:57 PM Last Post By: Marko Majic
Marko Majic

Posts: 14
Registered: 1/20/03
Closing application on startup  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 4, 2016 11:36 AM
This is a rather basic functionality question which, to my embarrassment, I've never found the adequate solution (other than "live with it") - but, I thought, hey maybe the smart forum folk can help!

So, the story is that I startup my (VCL) application (create all auto-create forms, call Application->Run() - standard stuff) and then in the OnShow event of the application's main form I check for some basic requirements for the application to run. Then, if some things are not up to scratch, I show a message and close the application (by calling {Close(); return;} from the OnShow() event handler.

Sort of, like this:

void __fastcall TMainFrm::FormShow(TObject *Sender)
{
	if(!InitGlobals()) {
		Close();
		return;
	}
 
	// some other code (enabling/disabling controls etc.)
       // ...
}


For the most part, this works fine (i.e. as intended) except that, on application close, it always produces this annoying "flash" as the main window gets actually created (displayed) and then quickly closed...

In some other applications, I've gotten around this by doing the startup check in _tWinMain() and, basically, bypassing the Application->Run() call if some of the conditions are not met. But, in some other ones, I prefer to do it in the main form (after all of the forms and data modules have already been created). Also, in general, as the project files need to be recreated with pretty much every IDE upgrade, I prefer to keep the main source file as "stock" as possible (so as to avoid having to customize main source files every time).

However, I was never able to figure out how to avoid the "flash" of the form being displayed before being closed. I tried (the obvious) route of setting the Visible property to false - both in OnShow() as well as in OnActivate() callbacks (if my global initialization flag shows that the application should stop) but that, of course, does not work (throws an exception).

The other thing I tried was to set the state of the main form to minimized (before checking) and back to restored (if startup check is OK) but not if it failed. This works in that it doesn't produce a "flash" of form creation on closing - however, the problem is that, when the message box is displayed (to describe the reason application failed to start), if the taskbar icon is clicked - the application crashes. Setting Application->MainFormOnTaskBar = false; does not work from the OnShowEvent (it throws the same exception as when trying to set Visible to false). I suppose I could try setting MainFormOnTaskBar in _tWinMain() but, as I mentioned before, I prefer keeping _tWinMain() stock).

So, the upshot is, since I imagine this is a fairly commone usage scenario - I was wondering how others are handling the checking the environment and stopping the application from running (gracefully)?

Cheers,

Marko
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: Closing application on startup
Helpful
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 4, 2016 12:02 PM   in response to: Marko Majic in response to: Marko Majic
Marko wrote:

in the OnShow event of the application's main form I check
for some basic requirements for the application to run.

Those kinds of checks should be made before the MainForm is even created,
before Application->Run() is called.

Then, if some things are not up to scratch, I show a message and
close the application (by calling {Close(); return;} from the
OnShow() event handler.

You should not Close() a Form in its OnShow event. Use Application->Terminate()
instead.

For the most part, this works fine (i.e. as intended) except that, on
application close, it always produces this annoying "flash" as the
main window gets actually created (displayed) and then quickly
closed...

All the more reason to perform the checks before the MainForm is created.

In some other applications, I've gotten around this by doing the
startup check in _tWinMain() and, basically, bypassing the
Application->Run() call if some of the conditions are not met.

That is exactly what you should be doing.

But, in some other ones, I prefer to do it in the main form (after all
of the forms and data modules have already been created).

Then you haven't structured your code correctly. A Form UI should only be
interacting with your user and displaying your data to the user, not driving
your app's business logic. DataModules are a convenience for managing non-visual
components, database connections, etc. They shouldn't be tied to your UI.

At the very least, if you need to, auto-create your DataModules first, then
use them as needed to validate your startup data, and then finally create
the UI Forms only if the app is not going to terminate.

Also, in general, as the project files need to be recreated with pretty
much every IDE upgrade, I prefer to keep the main source file as "stock"
as possible (so as to avoid having to customize main source files every
time).

Then at the very least, do your startup checks in the MainForm (or a DataModule)
constructor, not in the OnShow event. If you need to terminate the app,
the constructor can either:

1. throw an exception to cancel its construction, and thus bypass Application->Run().

2. call Application->Terminate(), which will delay the termination until
Application->Run() is called. To avoid the "flash", set Application->ShowMainForm
to false (which you can't do in the MainForm's OnShow event since the MainForm
is already in the process of being shown).

So, the upshot is, since I imagine this is a fairly commone usage
scenario - I was wondering how others are handling the checking the
environment and stopping the application from running (gracefully)?

The correct way is to perform the checks before creating the UI at all.
But that means modifying _tWinMain(). Performing the checks in an auto-created
constructor would be a viable alternative.

--
Remy Lebeau (TeamB)
Marko Majic

Posts: 14
Registered: 1/20/03
Re: Closing application on startup  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Apr 4, 2016 12:57 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Hi Remy,

Thank you for taking the time to answer my questions. If I remember correctly (and this WAS some years ago when I made this change :-)) but (another) reason (aside from the fact that I learned the value of keeping the autogenerated main source file intact) I switched to doing my startup checks in the OnShow event is that a lot of my code is in packages and, early on (in a lot earlier version of Builder) I was getting some strange exceptions when performing these checks from _tWinMain() which I traced to the fact that some of my globals that were defined in packages (global variable instances of classes in packages) were not initialized by the time code in _tWinMain() was executed. The only way I could get around it (at that time) was to defer tests until later.

I also think that bypassing the UI creation altogether is a more elegant way of terminating so I think I'll check if the problem is still there if I do it from _tWinMain() (it may have been fixed in subsequent releases). It's fairly easy to check it out as all of my custom initialization tests are centralized in a single function call (although tests themselves rely on different global class instances from a number of different packages linked to the application).

Cheers,

Marko
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02