Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Forms Delphi onshow主窗体/模态窗体_Forms_Delphi_Modal Dialog - Fatal编程技术网

Forms Delphi onshow主窗体/模态窗体

Forms Delphi onshow主窗体/模态窗体,forms,delphi,modal-dialog,Forms,Delphi,Modal Dialog,我有一个项目,它有一个主窗体和一些其他窗体。 当应用程序加载时,它需要执行一些任务,并在主窗体顶部的模式窗体中显示结果。 我遇到的问题是,如果我调用函数来执行任务/在主窗体中创建并显示模态窗体,则模态窗体将显示,但主窗体在模态窗体关闭之前不会显示,这就是我所期望的情况。为了解决这个问题,我在主窗体中添加了一个计时器,并在主窗体的onshow事件中启动它。计时器调用函数来执行任务/创建和显示模式窗体。所以现在主形式出现在模态形式之前 但是我不认为这是最好的解决方案,我想知道是否有人能提供更好的解决

我有一个项目,它有一个主窗体和一些其他窗体。 当应用程序加载时,它需要执行一些任务,并在主窗体顶部的模式窗体中显示结果。 我遇到的问题是,如果我调用函数来执行任务/在主窗体中创建并显示模态窗体,则模态窗体将显示,但主窗体在模态窗体关闭之前不会显示,这就是我所期望的情况。为了解决这个问题,我在主窗体中添加了一个计时器,并在主窗体的onshow事件中启动它。计时器调用函数来执行任务/创建和显示模式窗体。所以现在主形式出现在模态形式之前

但是我不认为这是最好的解决方案,我想知道是否有人能提供更好的解决方案

我正在使用Delphi7


Colin

一个常用的选择是在表单的
上发布消息。像这样:

const
  WM_SHOWMYOTHERFORM = WM_USER + 0;

type
  TMyMainForm = class(TForm)
    procedure FormShow(Sender: TObject);
  protected
    procedure WMShowMyOtherForm(var Message: TMessage); message WM_SHOWMYOTHERFORM;
  end;

...


procedure TMyMainForm.FormShow(Sender: TObject);
begin
  PostMessage(Handle, WM_SHOWMYOTHERFORM, 0, 0);
end;

procedure TMyMainForm.WMShowMyOtherForm(var Message: TMessage);
begin
  inherited;
  with TMyOtherForm.Create(nil) do begin
    try
      ShowModal;
    finally
      Free;
    end;
  end;
end;
type
  TMyMainForm = class(TForm)
  private
    FMyOtherFormHasBeenShown: Boolean;
  protected
    procedure CMShowingChanged(var Message: TMessage); message CM_SHOWINGCHANGED;
  end;

.....

procedure TMyMainForm.CMShowingChanged(var Message: TMessage);
begin
  inherited;
  if Showing and not FMyOtherFormHasBeenShown then begin
    FMyOtherFormHasBeenShown := True;
    with TMyOtherForm.Create(nil) do begin
      try
        ShowModal;
      finally
        Free;
      end;
    end;
  end;
end;

为什么不在activate上使用
main表单呢

procedure TMyMainForm.FormActivate(Sender: TObject);
begin
  //Only execute this event once ...
  OnActivate := nil;

  //and then using the code David Heffernan offered ...
  with TMyOtherForm.Create(nil) do begin
    try
      ShowModal;
    finally
      Free;
    end;
end;

将事件设置为nil将确保此代码在启动时只运行一次。

在调用Windows API函数
ShowWindow
之前立即触发
OnShow
事件。正是对
ShowWindow
的调用实际导致窗口出现在屏幕上

因此,理想情况下,您需要在调用
ShowWindow
后立即运行一些东西。事实证明,驱动这一切的VCL代码位于
TCustomForm
消息处理程序中,用于
CM\u SHOWINGCHANGED
。该消息处理程序触发
OnShow
事件,然后调用
ShowWindow
。因此,一个很好的解决方案是在
CM\u SHOWINGCHANGED
处理程序运行后立即显示模态形式。像这样:

const
  WM_SHOWMYOTHERFORM = WM_USER + 0;

type
  TMyMainForm = class(TForm)
    procedure FormShow(Sender: TObject);
  protected
    procedure WMShowMyOtherForm(var Message: TMessage); message WM_SHOWMYOTHERFORM;
  end;

...


procedure TMyMainForm.FormShow(Sender: TObject);
begin
  PostMessage(Handle, WM_SHOWMYOTHERFORM, 0, 0);
end;

procedure TMyMainForm.WMShowMyOtherForm(var Message: TMessage);
begin
  inherited;
  with TMyOtherForm.Create(nil) do begin
    try
      ShowModal;
    finally
      Free;
    end;
  end;
end;
type
  TMyMainForm = class(TForm)
  private
    FMyOtherFormHasBeenShown: Boolean;
  protected
    procedure CMShowingChanged(var Message: TMessage); message CM_SHOWINGCHANGED;
  end;

.....

procedure TMyMainForm.CMShowingChanged(var Message: TMessage);
begin
  inherited;
  if Showing and not FMyOtherFormHasBeenShown then begin
    FMyOtherFormHasBeenShown := True;
    with TMyOtherForm.Create(nil) do begin
      try
        ShowModal;
      finally
        Free;
      end;
    end;
  end;
end;

使用PostMessage。抱歉,为什么这个问题在主要问题列表中显示为“模糊”这一离题?@kobik:AFAIK问题在有一个你忽略的标记时显示为灰色,并且当他们的反对票分数超过某个限制时显示为灰色。顺便说一句,关于SO工作方式的问题最好在元站点上提问(请参阅主导航中的链接)。@Marjan,感谢您提供的信息。虽然这是解决方案的正确想法,但所示的实施情况并不太好。:)使用自定义消息,并为该特定消息实现一个处理程序,而不是替换整个WndProc。只需在表单的类型声明之前声明自定义消息,并添加
procedure-umshowmotherform(var-message:TMessage);信息UM_showmotherform。那么,唯一中断正常的
WndProc
流的是您的自定义消息。@Ken True。我习惯于处理在运行时分配的消息ID这是我之前的人处理的方式,所以我一直这样做,因为它是有效的。如果你有一些技术细节,那就太好了。@Dave和Ken-谢谢你的帮助。非常有用我不使用
ProcessMessages
。曾经所以不可能有。我也不使用使用
ProcessMessages
的第三方组件。而且我不使用没有来源的第三方组件,所以它们不能偷偷经过。:)