gpt4 book ai didi

multithreading - 为什么 TApplication.MessageBox 自动关闭?

转载 作者:行者123 更新时间:2023-12-04 06:50:20 25 4
gpt4 key购买 nike

我有一个应用程序需要几秒钟才能加载(大量初始化)。 GUI 在启动期间卡住。所以我想创建一个在应用程序加载时淡入和淡出的启动屏幕。我用TBackgroundWorker组件在后台线程中执行动画。

但是,当我使用此组件时,会发生一些奇怪的事情:当它发出“工作完成”信号时(请参阅BackgroundWorkerWorkComplete),我同时打开的消息对话框会自动关闭。

procedure TMainForm.ButtonStartSplashClick(Sender: TObject);
VAR
frmSplash: TfrmSplash;
begin
frmSplash:= TfrmSplash.Create(NIL);
frmSplash.StartAnimation;

//MessageBox(Handle, 'Hi', nil, MB_OK); // This remains on screen
Application.MessageBox(PChar('Hi'), PChar('Box'), MB_ICONINFORMATION); // This is automatically closed when the background thread is done
end;

这是启动屏幕:

procedure TfrmSplash.StartAnimation;
begin
Show;
BackgroundWorker.Execute;
end;


procedure TfrmSplash.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action:= caFree;
end;


procedure TfrmSplash.BackgroundWorkerWork(Worker: TBackgroundWorker);
VAR i: Integer;
begin
for i:= 1 to 255 DO
begin
AlphaBlendValue:= i; // do not access GUI directly from thread
Sleep(30);
end;
end;


procedure TfrmSplash.BackgroundWorkerWorkComplete(Worker: TBackgroundWorker; Cancelled: Boolean);
begin
Close; // At this point, the msg box will be closed also
end;

我觉得奇怪的是 MessageBox 保留在屏幕上,而 Application.MessageBox 没有(自动关闭)。

为什么关闭 TfrmSplash 也会关闭消息框?

最佳答案

TApplication.MessageBoxWinAPI MessageBox 的包装器功能。前者的代码向您展示了它的调用方式:

function TApplication.MessageBox(const Text, Caption: PChar; Flags: Longint): Integer;
var
ActiveWindow, TaskActiveWindow: HWnd;
MBMonitor, AppMonitor: HMonitor;
MonInfo: TMonitorInfo;
Rect: TRect;
FocusState: TFocusState;
WindowList: TTaskWindowList;
begin
ActiveWindow := ActiveFormHandle;
if ActiveWindow = 0 then
TaskActiveWindow := Handle
else
TaskActiveWindow := ActiveWindow;

{ ... }


try
Result := Winapi.Windows.MessageBox(TaskActiveWindow, Text, Caption, Flags);
finally

请注意,传递给 WinAPI 调用的 HWND 是 TaskActiveWindow,它在调用时被视为事件窗口(除非没有,在这种情况下使用应用程序的句柄)反而)。由于您刚刚创建了 TFrmSplash,因此它将成为事件窗口,并且当其父窗口(您的启动窗口)关闭时消息框将被释放。

当您直接调用 MessageBox 时:

 MessageBox(Handle, 'Hi', nil, MB_OK);   // This remains on screen

您正在传递Handle,它隐式是您调用代码的表单的句柄,在本例中是您的TMainForm,因此主表单变为在这种情况下,所有者与启动画面无关。

关于multithreading - 为什么 TApplication.MessageBox 自动关闭?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60241794/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com