使用ModalResult退出表单

时间:2011-05-17 19:58:52

标签: delphi forms

我有一堆表格,我想让它们自动化,这样它们就可以自己打开和关闭。

我知道如何让它们打开(通过使用OnActivate功能),但我无法关闭它们。

所以,例如,我有

procedure TProgressForm.FormActivate(Sender: TObject);
begin
  inherited;
  if FModItem.IsInQueue then
    begin
      RunBtnClick(Self);
      ModalResult := mrOK;
    end;    
end;

运行一个函数。我希望在函数运行后关闭窗口,这就是ModalResult应该做的事情。

(我也尝试在RunBtnClick程序的最后添加ModalResult行,但这也不起作用)

我正在创建这样的表单:

ProgForm := TProgressForm.Create(Self, FModItem);
Self.Visible := False;
try
 if ProgForm.ShowModal = mrOK then
  begin
    Left := ProgForm.Left;
    Top := ProgForm.Top;
  end;

我已经能够通过向对象检查器中的模态结果添加mrOK来创建关闭表单的按钮,但我似乎无法明确地执行此操作

谁能明白为什么它不起作用?

由于

4 个答案:

答案 0 :(得分:15)

不工作的原因是VCL在显示表单后在TCustomForm.ShowModal中主动将ModalResult设置为0,但在开始检查对ModalResult的更改之前。所以在OnActivate和OnShow中,你要早。

解决方案是延迟通知。这可以通过PostMessage完成,如下所示:

const
  UM_ACTIVATED = WM_USER + 1;

type
  TProgressForm = class(TForm)
    procedure FormActivate(Sender: TObject);
  private
    procedure UMActivated(var Message: TMessage); message UM_ACTIVATED;
  end;

...

procedure TProgressForm.FormActivate(Sender: TObject);
begin
  PostMessage(Handle, UM_ACTIVATED, 0, 0);
end;

procedure TProgressForm.UMActivated(var Message: TMessage);
begin
  { Your code here }
  ModalResult := mrOk;
end;

来源:NLDelphi

答案 1 :(得分:6)

我会覆盖ShowModal并执行您现在在那里OnActvate进行的测试。这有两大优点:

  • 如果不需要显示,则不显示格式。从OnActivate启动表单关闭会导致表单在屏幕上“闪烁”:显示并立即关闭。
  • 不依赖于您无法控制的代码。您不再关心祖先ShowModal中的操作顺序,因为只有在需要实际显示表单时才会调用它。

当然,使用GUI元素(表单)这种方式有点代码味道,因为它基本上使用GUI而不需要用户交互。毫无疑问,这可以使用中间函数进行重构,该函数返回mrOk并执行RunBtnClick()无需GUI的操作,并仅在需要时创建Form。我想这是一种成本效益的情况。

代码:

TMyForm = class(TForm)
....
public
  function ShowModal:Integer;override;
end;

function TMyForm.ShowModal:Integer;
begin
  if FModItem.IsInQueue then
    begin
      RunBtnClick(Self);
      Result := mrOK;
    end
  else
    Result := inherited ShowModal;
end;

答案 2 :(得分:3)

在ModustResult在TCustomForm.ShowModal中重置为mrNone之前触发OnActivate事件。这意味着将忽略更改OnActivate处理程序中的ModalResult。

  function TCustomForm.ShowModal: Integer;
  Show;
  try
    SendMessage(Handle, CM_ACTIVATE, 0, 0);  << Your onActivate is called here
    ModalResult := 0; << ModalResult is reset

答案 3 :(得分:2)

查看TCustomForm.ShowModal(在forms.pas中):在发送CM_ACTIVATE消息之后 首先检查ModalResult(所述消息触发你的OnActivate调用);实际上,在OnActivate调用返回后,它立即设置为 0 ,所以难怪你的任务无法正常工作。

我不想太乱用这个(你的代码肯定没有通过气味测试),但是你可以尝试添加类似的东西:

if ModalResult=0 then 
     SendMessage(Handle, CM_ACTIVATE, 0, 0);

到事件处理程序的顶部。