Delphi 2009 - Close all function from taskbar stops processing if presented with MessageDlg?

813 Views Asked by At

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:

  1. 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).
  2. Each child window has its parent set to the desktop (in order to get it displaying on the Taskbar).
  3. 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:

  1. Regardless if I select "Yes/No" the Close All process seems to stop after that particular window is closed.
  2. 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?

2

There are 2 best solutions below

5
On BEST ANSWER

Windows doesn't send WM_CLOSE messages to these windows, it posts WM_SYSCOMMAND with the SC_CLOSE request. This in turn leads to the sending of WM_CLOSE messages if the standard Windows message box is used. If the MessageDlg() function is used instead, only the first posted WM_SYSCOMMAND leads to a WM_CLOSE, the others do not. It's hard to say for sure, but maybe this has something to do with the DisableTaskWindows() and EnableTaskWindows() calls that the VCL uses to "fake" modal dialogs. If you replace the Windows function with Application.MessageBox(), a wrapper that does use DisableTaskWindows() and EnableTaskWindows(), then it doesn't work either (which IMO supports this reasoning).

1
On

I think I can explain why switching from MessageDlg to MessageBox made things different. MessageDlg in turn calls the MessageDlgPosHelp which creates a Delphi form to look like the Windows MessageBox, and this form is called shown with ShowModal. This locks the entire application until it is closed.

MessageBox, on the other hand, defaults to MB_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 the hwnd parameter, so other windows in your application are still accessible.