Delphi7,Showmessage命令在应用程序窗体出现之前执行

Delphi7,Showmessage命令在应用程序窗体出现之前执行,delphi,action,message,Delphi,Action,Message,我想知道为什么“showmessage”命令在应用程序窗体出现之前执行,我的意思是,每当我运行程序时,首先出现消息,然后出现应用程序窗体: procedure TForm1.FormCreate(Sender: TObject); begin button1.hide; button2.hide; image3.picture.loadfromfile('c:\EAS\std.bmp'); showmessage ('Hi'); end; end. delphi做的第一件事就是显示消息“Hi

我想知道为什么“showmessage”命令在应用程序窗体出现之前执行,我的意思是,每当我运行程序时,首先出现消息,然后出现应用程序窗体:

procedure TForm1.FormCreate(Sender: TObject);
begin
button1.hide;
button2.hide;
image3.picture.loadfromfile('c:\EAS\std.bmp');
showmessage ('Hi');
end;

end.
delphi做的第一件事就是显示消息“Hi”。然后它完成其余的工作(表单显示、隐藏按钮、加载图像等)。即使showmessage是最后一个,它也是首先执行的。在窗体显示、按钮隐藏和图像加载后,如何使消息显示


感谢

原因是表单在显示之前已创建(因此,
OnCreate
被激发)

解决方案1

一种解决方案是在创建表单时向表单发布窗口消息。试试这个:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

const
  WM_GREETING = WM_USER + 1;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
  protected
    procedure WMGreeting(var Message: TMessage); message WM_GREETING;
  public
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

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

procedure TForm1.WMGreeting(var Message: TMessage);
begin
  ShowMessage('Created and shown!');
end;

end.
解决方案2

另一种解决方案是使用
OnActivate
事件,该事件在表单每次获得键盘焦点时调用:向表单类添加私有字段
FMessageShown:boolean
。然后,在激活的
中,如果标志为false(默认情况下为类的字段),则显示消息并将标志设置为true:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TForm1 = class(TForm)
    procedure FormActivate(Sender: TObject);
  private
    { Private declarations }
    FMessageShown: boolean;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormActivate(Sender: TObject);
begin
  if not FMessageShown then
  begin
    ShowMessage('Created and shown.');
    FMessageShown := true;
  end;
end;

end.
实际上,这两种方法都非常有效。第一种解决方案的缺点是,它可能在某种程度上依赖于“实现细节”,而后一种解决方案的缺点是非常明显的:每次表单regets键盘焦点时都会检查一个标志,甚至在表单最初创建和消息显示数周后也是如此

解决方案3

一个既没有缺点,又假定您不需要为其他目的而激活
事件的解决方案,就是在事件第一次(因此仅)执行后“取消分配”事件:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TForm1 = class(TForm)
    procedure FormActivate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormActivate(Sender: TObject);
begin
  ShowMessage('Created and shown.');
  OnActivate := nil;
end;

end.

(但是,如果您将
OnActivate:=nil
替换为
OnActivate:=MySecondEventHandler
),这种方法可以扩展到您确实需要用于其他目的的事件的情况下)

我宁愿将
OnShow
事件的消息发布到自身。@TLama:但是如果表单被隐藏,然后再次显示,消息将再次出现。但您可能可以在
OnCreate
中发布消息。回答!请随意将其包含在您的答案中。您的想法是从
OnCreate
事件发布该消息。关键是您不需要依赖异步消息分派。目标是在窗口出现在屏幕上时执行某些操作。因为系统会通知你,在我看来,最好对此做出回应。所以伙计们,在你们进行了很长时间的讨论之后:P,哪一个是最好的方法?