莫代尔表格不会关闭

时间:2014-09-29 13:39:28

标签: forms delphi event-handling

我有一个模态表单,显示冗长操作的进度。触发Form的OnActivate事件时会触发该操作。

procedure TMyForm.FormActivate(Sender:TObject);
begin
  Start;
end;

表单有一个取消按钮,ModalResult属性设置为mrCancel,OnClick处理程序设置一个标志,导致操作结束。

procedure TMyForm.CancelButtonClick(Sender: TObject);
begin
  FCancel := True;
end;

当我单击取消按钮时,它会按预期停止操作,但无法关闭表单。我怀疑这是因为OnActivate处理程序阻止表单关闭。再次单击该按钮可关闭表单。我尝试过调用Close并发送一条wm_close消息,但似乎没有任何效果。有没有人有任何建议让表格在第一次点击时作出回应?也许我可以使用另一个事件而不是OnActivate?

我知道将建议将操作移动到一个线程。由于大量遗留代码写得不好,目前不太可能。

1 个答案:

答案 0 :(得分:3)

在下文中,我将假设消息可能是通过调用任务中的Application.ProcessMessages来处理的。

让我们看一下相关的代码ShowModal

SendMessage(Handle, CM_ACTIVATE, 0, 0);
ModalResult := 0;
repeat
  Application.HandleMessage;
  if Application.Terminated then ModalResult := mrCancel else
    if ModalResult <> 0 then CloseModal;
until ModalResult <> 0;

SendMessage调用导致OnActivate事件触发。在您的代码中,然后启动任务,直到任务完成后才返回。您已分配到ModalResult的那一点。但请稍等,上面摘录中的下一行会将ModalResult设置回0,因此您的设置会丢失。因此输入了模态消息循环,您需要再次分配给ModalResult以使表单关闭。

这里的底线是在进入模态消息循环之前无法执行任务。一种解决方案是将长时间运行的任务放在单独的线程中。如果您无法做到这一点,您可以在OnActivate事件处理程序中向表单发布消息。通过启动任务来响应事件。此时,模态消息循环将运行,设置ModalResult将关闭表单。