为什么MessageBox不会在同步线程上阻止应用程序?

Ben*_*iss 8 delphi vcl tthread

据我了解并了解TThread类的方法,如果你同步你的代码,它实际上是在主应用程序线程中执行的(就像一个计时器/按钮点击/等).我一直在玩,并注意到MessageBox不会阻止主应用程序,但是睡眠就像预期的那样.这是为什么?

type
  TTestThread = class(TThread)
  private
    procedure SynchThread;
  protected
    procedure Execute; override;
  public
    constructor Create(CreateSuspended: Boolean);
  end;

procedure TTestThread.SynchThread;
begin
 MessageBoxA (0, 'Hello', 'Test', 0);
end;

procedure TTestThread.Execute;
begin
 Synchronize (SynchThread)
end;

constructor TTestThread.Create(CreateSuspended: Boolean);
begin
  inherited;
  FreeOnTerminate := True;
end;

procedure StartThread;
var
 TestThread : TTestThread;
begin
 TestThread := TTestThread.Create (FALSE);
end;
Run Code Online (Sandbox Code Playgroud)

gab*_*abr 13

这个答案分为两部分.

第1部分很好地解释了如果MessageBox()/ related是同步的,为什么我的消息循环不会冻结?.MessageBox函数没有阻塞,它只是创建一个带有自己的消息循环的对话框.

MessageBox文档中解释了第2部分.

hWnd:要创建的消息框的所有者窗口的句柄.如果此参数为NULL,则消息框没有所有者窗口.

当您显示模式对话框时,Windows会禁用其所有者,但如果您为第一个参数传递0,则没有所有者,也没有禁用任何内容.因此,您的程序将在显示消息框时继续处理消息(并对其作出反应).

要更改此行为,请将表单的句柄作为第一个参数传递.例如:

procedure TTestThread.SynchThread;
begin
  MessageBoxA (Form1.Handle, 'Hello', 'Test', 0);
end;
Run Code Online (Sandbox Code Playgroud)

  • 你的第2部分不准确.没有所有者不会更改哪个消息循环拉出消息.MessageBox仍然是同步的,直到它返回,它的消息循环拉出排队的消息.将所有者窗口传递给模式对话框时,模式对话框将禁用所有者,其所有者等. (3认同)

Dav*_*nan 12

我怀疑这个问题归结为当你说:

消息框不会阻止主应用程序.

我的意思是,当您显示消息框时,您的VCL表单仍然可以与之交互.这里的问题与线程无关,我建议我们将它们从等式中删除.你对什么Synchronize是合理的理解.

这个问题完全与窗口所有者的概念有关,以及模态对话框窗口对其所有者的行为方式.请注意,所有者,我不是指Delphi属性TComponent.Owner,而是指所有者的Windows API含义.

创建一个VCL应用程序并在表单上删除两个按钮.添加以下OnClick处理程序.

procedure TForm1.Button1Click(Sender: TObject);
begin
  MessageBox(0, 'Not owned', nil, MB_OK);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  MessageBox(Handle, 'Owned by the VCL form', nil, MB_OK);
end;
Run Code Online (Sandbox Code Playgroud)

现在观察点击时会发生什么Button1.消息框显示,但您仍然可以单击VCL表单.并与之比较Button2.当它显示消息框时,无法与VCL表单进行交互.

显示模式对话框窗口时,对话框窗口将禁用其所有者.在这种情况下Button2,所有者是VCL表格.一旦表单被禁用,您就无法与其进行交互.在这种情况下Button1,没有所有者,因此模态对话框窗口不会禁用任何其他窗口.这就是为什么VCL表格可以与之互动的原因.

Raymond Chen在他的Old New Thing博客上有一个关于模态的长篇系列: