我有一个模态表单,显示冗长操作的进度。触发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?
我知道将建议将操作移动到一个线程。由于大量遗留代码写得不好,目前不太可能。
答案 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
将关闭表单。