为什么在通过OnClose事件(在线程中)释放表单后不显示MessageDlg

Jas*_*son 4 delphi multithreading dialog delphi-xe6

鉴于这种情况:

procedure TForm2.Button1Click(Sender: TObject);
var
  Form: TForm;
begin
  Form := TForm.Create(nil);
  Form.OnClose := FormClosed;
  Form.Show;
  Sleep(200);
  TThread.CreateAnonymousThread(
    procedure
    begin
      TThread.Synchronize( nil, 
        procedure 
        begin 
          Form.Close; 
          MessageDlg('Testing', mtInformation, [mbok], 0); 
        end);
    end).Start;
end;

procedure TForm2.FormClosed(Sender: TObject; var Action: TCloseAction);
begin
  Action := TCloseAction.caFree;
end;
Run Code Online (Sandbox Code Playgroud)

我的MessageDlg调用未显示(此调用的结果始终为mrCancel(2)).

在挖掘之后,它与OnClose事件相关并将Action设置为caFree.

改变Form.CloseForm.Free和删除OnClose事件完全显示的MessageDlg确定.在调用Form.Close 之前放置MessageDlg 可以正常工作.最初我认为我的Form变量的范围可能导致了问题,但Form在TForm2实例中声明为私有字段并不能解决问题.

我的目标是显示一个启动窗体,执行我的线程,然后通过所述线程的回调,关闭Splash窗体并在适当的位置显示对话框.

为清楚起见,为什么会这样?

Dav*_*nan 7

发生的事情是对话框的拥有窗口是正在关闭的表单.当对话框启动其模态消息循环时,表单将被释放并随之取消其拥有的窗口.包括对话框.

对此进行测试,通过替换调用以首先显示对话框,让您更有信心我上面所述的内容是正确的

MessageBox(0, ...);
Run Code Online (Sandbox Code Playgroud)

然后用

MessageBox(Form.Handle, ...);
Run Code Online (Sandbox Code Playgroud)

也就是说,明确对话框的所有者.

没有所有者的第一个版本将显示该对话框.第二个不会因为它复制代码中的场景.

  • 我跟踪并验证了这种情况.调试器将TCustomTaskDialog.Execute中的LParentWnd修改为0,并显示对话框.否则,对话框会将活动窗口作为其所有者,然后将其拉到脚下. (4认同)