在我的应用程序主表单可见后,如何直接进行对话框?

X-R*_*Ray 6 delphi delphi-xe

我一直在使用TFormOnActivate事件让我有机会在我的应用程序启动后立即显示一个对话框.我希望主窗体已经加载和可见.这样做的好方法是什么?

我发现OnActivate除非形式WindowState是正常的,否则它会正常工作wsMaximized.

在过去,我已经以各种方式完成了我想要的东西,但我希望有更好的方法.

这对我有用:

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;
Run Code Online (Sandbox Code Playgroud)

有没有更好的办法?

and*_*ius 17

在窗体的OnCreate事件处理程序中发布用户消息并在消息的处理程序中显示对话框:

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;
Run Code Online (Sandbox Code Playgroud)

虽然我发现计时器方法更好:只需在表单上删除一个计时器组件,将Interval设置为100(ms)并实现OnTimer事件:

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

  form2 := TForm2.Create(Application); 
  form2.ShowModal;
end;
Run Code Online (Sandbox Code Playgroud)

两种方法的区别在于:

当从OnCreate或OnShow处理程序发布用户消息时,将使用普通优先级调度消息,这意味着其他窗口初始化消息可能会在其后发布和处理.实质上,WM_PAINT消息将在UM_DLG消息之后处理.如果UM_DLG消息需要很长时间才能处理而不会抽取消息队列(例如,打开数据库连接),那么表单将显示为空白而不绘制客户区域.

WM_TIMER消息是一个低优先级消息,并且意味着首先处理表单初始化消息,然后才处理WM_TIMER消息,即使在表单创建完成之前发布WM_TIMER消息也是如此.

  • 计时器对我来说似乎很可疑.事件可能会在主表单显示之前触发我猜.在OnShow中发布消息有什么问题? (5认同)

Rem*_*eau 1

在 MainForm 的OnShow事件中,您可以执行以下操作之一,以在延迟后显示对话框,以便 MainForm 首先完全显示自身:

  • 启动一个短定时器。
  • PostMessage()给自己的自定义窗口消息。
  • 使用TThread.CreateAnonymousThread()TTask来调用TThread.Queue().
  • 使用TThread.ForceQueue()(仅限 10.2 东京及更高版本)。