开发者

How can I make a a dialog box happen directly after my app's main form is visible?

I have been using TForm's OnActivate event to give me the opportunity to show a dialog box as soon as my app has started. I want the main form to already be loaded & visible. What's a good way to do this?

I have found that OnActivate works fine unless the forms WindowState is wsMaximized.

in the past I've accomplished what I want in various ways but 开发者_如何学GoI expect there is a better way.

Here's what worked for me:

procedure TForm1.FormCreate(Sender: TObject);  
begin 
  Application.OnIdle:=OnIdle; 
end; 

procedure TForm1.OnIdle(Sender: TObject; var Done: Boolean); 
begin 
  Application.OnIdle:=nil; 
  form2:=TForm2.Create(Application); 
  form2.ShowModal; 
end;

Is there a better way?


In the form's OnCreate event handler post a user message and show the dialog in the handler of the message:

unit Unit1;

interface

const
  UM_DLG = WM_USER + $100;

type
  TForm1 = class(TForm)
  ...
  procedure UMDlg(var Msg: TMessage); message UM_DLG;
...

implementation

procedure TForm1.FormCreate(Sender: TObject);
begin
  PostMessage(Handle, UM_DLG, 0, 0);
end;

procedure TForm1.UMDlg(var Msg: TMessage);
begin
  form2 := TForm2.Create(Application); 
  form2.ShowModal; 
end;

Although I found timer approach even better: just drop a timer component on the form, set Interval to 100 (ms) and implement OnTimer event:

procedure Timer1Timer(Sender: TObject);
begin
  Timer1.Enabled := False; // stop the timer - should be executed only once

  form2 := TForm2.Create(Application); 
  form2.ShowModal;
end;

The difference between the two approaches is:

When user message is posted either from OnCreate or OnShow handler, the message is dispatched with normal priority which means that other window initialization messages might get posted and handled after it. For essence, WM_PAINT messages would be handled after UM_DLG message. If UM_DLG message is taking long time to process without pumping the message queue (for example, opening db connection), then form would be shown blank without client area painted.

WM_TIMER message is a low-priority message and than means that form initialization messages would be handled first and only then WM_TIMER message would be processed, even if WM_TIMER message is posted before the form creation completes.


In the MainForm's OnShow event, you can do one of the following to show the dialog box after a delay that allows the MainForm to finish fully showing itself first:

  • start a short timer.
  • PostMessage() a custom window message to yourself.
  • use TThread.CreateAnonymousThread() or TTask to call TThread.Queue().
  • use TThread.ForceQueue() (10.2 Tokyo and later only).


The way I ended up doing it was to use the Application.OnIdle event. It's not a perfect solution but it does work for my situation. Thank you all for your answers!


I was shown the following method of doing this long ago and it's always worked for me.

In your main form OnCreate method, after you've done anything you might normally do in this method, add the following line:

Self.Show;

This will display the main form.

Then, after that, enter the code to display your dialog box.

When run, your main form will display followed immediately by your dialog box.


Well, I do not know if it is the best pratice, but I do like this:

In the PROGRAM file (.dpr - I use Delphi 7) I add this lines:

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Form1.Show;                                // Show Main Form
  Form1.Button1.Click;                       // Call event/function
  Application.Run;
end.

Please, someone correct me if it is not the best pratice!

Hope to be helpfull for you!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜