Delphi 2009 - 如果出现 MessageDlg,则关闭任务栏上的所有功能会停止处理吗?
当使用 MessageDlg 并尝试通过任务栏关闭所有/组命令关闭我的应用程序时,我注意到一个奇怪的行为。
我的应用程序如下:
- 有一个隐藏的主窗体,除了处理一些Windows消息并将它们传递到子窗口(如果需要)之外,它不做任何事情。
- 每个子窗口都将其父窗口设置为桌面(以便使其显示在任务栏上)。
- 每个孩子都有一个 OnClose 事件,该事件会弹出一个 MessageDlg 来提示用户是否要保存其会话(如果任何内容已被修改),
问题似乎是它会不断关闭任何尚未修改的窗口,然而,当它遇到一个已经存在的窗口时,两件事中的一件会间歇性地发生:
- 无论我是否选择“是/否”,关闭所有进程似乎都会在该特定窗口关闭后停止。
- 对话框未显示,结果是 mrCancel。关闭此窗口后,关闭所有进程将再次停止。
我所做的更改是使用 WinAPI MessageBox 函数代替了 MessageDlg,这似乎确实解决了问题。但是,我真的很想知道为什么 MessageDlg 会这样?
我最初的想法是,当对话框在“全部关闭”中间启动时,操作系统可能会向对话框发送一条 WM_CLOSE 消息,因为它在技术上是该组的一部分(这可以解释对话框没有出现并默认为 mrCancel,因为这相当于按 X)。但是,这并不能解释为什么在我关闭对话框后,“全部关闭”进程不会继续关闭组中的任何其他窗口!
对此有什么想法/想法吗?
I have noticed a strange piece of behaviour when using MessageDlg and attempting to close my application via the Taskbar close all/group command.
My application is as follows:
- There is a hidden main form which doesn't do anything other than handle some Windows Messages and pass them onto the child windows (if necessary).
- Each child window has its parent set to the desktop (in order to get it displaying on the Taskbar).
- Each child has an OnClose event which pops up a MessageDlg to prompt the user whether they want to save their session (if any content has been modified in anyway)
The issue seems to be it will continually close any windows that haven't been modified, however, when it hits a window that has been, 1 of 2 things are happening intermittently:
- Regardless if I select "Yes/No" the Close All process seems to stop after that particular window is closed.
- The dialog is not displayed and mrCancel is the result. Again the close all process stops after this window is closed.
A change I made was to use the WinAPI MessageBox function in replace of MessageDlg and this did seem to resolve the issue. However, I would really like to know why MessageDlg is acting like this?
My initial thought was when the dialog is being launched in the middle of the Close All perhaps the OS is sending a WM_CLOSE message to the dialog as it is technically part of the group (this would explain the dialog not appearing and defaulting to mrCancel as this is the equivalent of pressing the X). However, that doesn't explain why after I dismiss the dialog the Close All process does not continue to close any other windows in the group!
Any thoughts/idea's on this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Windows 不会向这些窗口发送
WM_CLOSE
消息,而是通过SC_CLOSE
请求发布WM_SYSCOMMAND
。如果使用标准 Windows 消息框,这又会导致发送WM_CLOSE
消息。如果改用MessageDlg()
函数,则只有第一个发布的WM_SYSCOMMAND
会导致WM_CLOSE
,其他则不会。很难确定,但这可能与 VCL 用于“伪造”模式对话框的DisableTaskWindows()
和EnableTaskWindows()
调用有关。如果将 Windows 函数替换为Application.MessageBox()
(一个使用DisableTaskWindows()
和EnableTaskWindows()
的包装器),则它不会也不起作用(IMO 支持这种推理)。Windows doesn't send
WM_CLOSE
messages to these windows, it postsWM_SYSCOMMAND
with theSC_CLOSE
request. This in turn leads to the sending ofWM_CLOSE
messages if the standard Windows message box is used. If theMessageDlg()
function is used instead, only the first postedWM_SYSCOMMAND
leads to aWM_CLOSE
, the others do not. It's hard to say for sure, but maybe this has something to do with theDisableTaskWindows()
andEnableTaskWindows()
calls that the VCL uses to "fake" modal dialogs. If you replace the Windows function withApplication.MessageBox()
, a wrapper that does useDisableTaskWindows()
andEnableTaskWindows()
, then it doesn't work either (which IMO supports this reasoning).我想我可以解释为什么从
MessageDlg
切换到MessageBox
会让事情变得不同。MessageDlg
依次调用MessageDlgPosHelp
,后者创建一个看起来像 WindowsMessageBox
的 Delphi 表单,并且该表单称为使用ShowModal 显示
。这将锁定整个应用程序,直到它关闭。另一方面,
MessageBox
默认为MB_APPLMODAL
,这意味着您必须先关闭它,然后才能使用它所附加的窗口。如果 uFlags 参数中没有指定任何内容,则这是默认值。这只会阻止您返回到hwnd
参数中指定的窗口,因此应用程序中的其他窗口仍然可以访问。I think I can explain why switching from
MessageDlg
toMessageBox
made things different.MessageDlg
in turn calls theMessageDlgPosHelp
which creates a Delphi form to look like the WindowsMessageBox
, and this form is called shown withShowModal
. This locks the entire application until it is closed.MessageBox
, on the other hand, defaults toMB_APPLMODAL
which means you have to close it before the window it is attached to can be used. If you have nothing specified in the uFlags parameter then this is the default. This only prevents you from getting back to the window specified in thehwnd
parameter, so other windows in your application are still accessible.