views:

271

answers:

2

Hi,

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?

A: 

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.

_J_
Good guess, but not true. It doesn't matter whether the `MessageBox()` call is window-modal, task-modal or even system-modal - it works in all cases.
mghie
+3  A: 

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).

mghie
Where you able to reproduce this issue then? Switching to the MessageBox does seem to work so I was going to just change over from MessageDlg.
James
Yes, I was able to reproduce it. As I wrote I believe it's rooted in the VCL handling of modal windows, so not using modal VCL windows is your easiest fix. Note that using the standard Windows function may have other benefits as well (transparent support of new UI styles, button caption language matches the OS default, ...).
mghie
James
If you want to implement "Yes to All" and "No to All" (which I think is a good idea UI-wise) you should reconsider the message box approach altogether. I like what Visual Studio does, it presents a special dialog with a list of modified files, and you can choose which ones you want to save (or all, or none of them). You could do something similar, which would make for a very clean UI while opening up a lot of additional possibilities.
mghie
At the minute this is probably something I would want to avoid as it is a bit of a major change. However, it's something to think about for the future. Thanks for your advice.
James