IceCold
IceCold

Reputation: 21202

Which is the best place to initialize code in VCL forms?

Possible Duplicate:
Splash Screen Programatically
Show a splash screen while a database connection (that might take a long time) runs

Which is the best place to initialize code such as loading INI file? I want first to show the form on screen so the user know that the app is loading and ONLY after that I want to call lengthy functions such as LoadIniFile or IsConnectedToInternet (the last one is REALLY slow).

The OnCreate is not good because the form is not yet ready and it will not show up on screen.

I do this I DPR but not working always:

program Test;
begin
  Application.Initialize;
  Application.Title := 'Test app';
  Application.CreateForm(TfrmTest, frmTest);
  frmTest.Show;               <---------------------- won't show
  LateInitialize;
  Application.Run;
end.

The form will not show until LateInitialize (4-5 seconds) is executed.


procedure LateInitialize;
begin
 CursorBussy;
 TRY
  // all this won't work also. the form won't show
  frmTest.Visible:= TRUE;
  Application.ProcessMessages; 
  frmTest.Show;
  Application.ProcessMessages;
  frmTest.BringToFront;
  frmTest.Update;
  Application.ProcessMessages;
  
  DoSomethingLengthy;     {4-5 seconds}
 FINALLY
  CursorNotBussy;
 END;
end;     <--------- Now the form shows.

And yes, frmTest it is my only form (the main form).

Upvotes: 2

Views: 1870

Answers (4)

Lars Bargmann
Lars Bargmann

Reputation: 142

An easy way to do this, is to send a message to yourself. I do this all the time

const
  MSG_AFTERCREATE = WM_APP + 4711;

...
procedure OnCreate(Sender: TObject);
procedure AfterCreate(var message: TMessage); message MSG_AFTERCREATE;
...


Implementation

procedure OnCreate(Sender: TObject);
begin
  PostMessage(Self.Handle, MSG_AFTERCREATE, 0, 0);
end;

procedure AfterCreate(var message: TMessage);
begin
  //Do initializing here... the form is done creating, and are actually visible now...
end;

Upvotes: 2

Arioch &#39;The
Arioch &#39;The

Reputation: 16065

Variant 1: Use TTimer with a 1 second delay, run it from main form's OnShow In TTimer do the initialisation This will give time for most components to initialize and draw themselves Variant 1.1: use message method in function and call Win API PostMessage (but not SendMessage aka Perform) from OnShow. This is seemilar but more cheap and fast. However that message "do init now" sometimes may be received before some complex component on the form would fully draw itself.

Variant 2: use threads (OmniThreadsLib or even plain TThread) Launch it from MainForm OnCreate and let it prepare all data in background, then enable all needed buttons, menus, etc That is truly the best way if you have long and blocking functions, liek you described IsConnectedToInternet.

Variant 3: use SplashScreen before showing main form. That is good because users see that application not read yet. That is bad for that very reason - people start feeling your program is slow. Google Chrome was told to draw their main form as picture in 1st moments just to make look "we are already started" even the actual control would be ready a bit later.

Upvotes: 1

Remy Lebeau
Remy Lebeau

Reputation: 597906

After calling frmTest.Show, you can call frmTest.Update to let it render onscreen, before then calling LateInitialize. But until Application.Run is called, the main message loop will not be running, so the form will not be able to do anything else until then.

Another option is to use the form's OnShow event to post a custom window message back to the form via PostMessage(), then have the form call LateInitialize when it receives that message at a later time. That will allow the form to process painting messages normally until LateInitialize is called.

Anything that blocks the main thread for more than a few milliseconds/seconds really should be moved into a separate worker thread instead (especially things like IsConnectedToInternet). The main thread should be used for running the UI.

Upvotes: 3

Max Williams
Max Williams

Reputation: 821

A long time ago in another forum far far away, someone posted the following to document the life cycle of a form. I have found it useful, so am sharing it here.

Create       OnCreate
Show         OnShow
Paint        OnPaint
Activate     OnActivate
ReSize       OnResize
Paint        OnPaint

Close query  OnCloseQuery
Close        OnClose
Deactivate   OnDeactivate
Hide         OnHide
Destroy      OnDestroy

Try the OnActivate event.

Upvotes: 0

Related Questions