Modality, part 6: Interacting with a program that has gone modal


Earlier we saw the importance of setting the right owner window for modal UI. It is also important, when manipulating a window, to respect its modality. For example, consider the program we ended up with last time, the one which calls the MessageBox function to display a modal dialog. If we wanted to get that program to exit and sent a WM_CLOSE message to the main window instead of its modal popup, the main window would likely exit and leave the message box stranded, resulting in the same stack trace without support we saw in part 4.

Respect the modality of a window. If it is disabled, don't try to get it to do things; it's disabled because it doesn't want to do anything right now. You can go hunting for its modal pop-up and talk to that pop-up. (Unless, of course, that pop-up is itself disabled, in which case you get to keep on hunting.)

Comments (14)
  1. Ben Hutchings says:

    In what situation might one want to do this?

  2. Is this why DDE is never fun when you have modal UI (particularly at startup)?

  3. I know it’s anthropomorphising but it’s not so much a case of windows are disabled because they don’t want to do anything right now – it’s more the case that some action they’ve caused would prefer that the parent window be disabled.

    Keep on writing Raymond – your blog is my number 1 read each morning.

  4. Isaac Chen says:

    In http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/windows/windowfeatures.asp

    "The system automatically destroys an owned window when its owner is destroyed."

    And as you said, we should set the owner of the pop up (or message box) properly. So we don’t seem to have a problem if WM_CLOSE is sent to (and processed by) the owner of the pop up (or message box). They both should be destroyed and thus leaving no stranded window (main or pop up/message box).

    Am I missing something?

  5. Raymond Chen says:

    Clearly something is wrong or the people in the messages I linked to are hallucinating. I already mentioned two reasons in the article.

  6. Ben Hutchings says:

    Raymond: In the first scenario, presumably EnumWindows temporarily blocks destruction of the windows whose handles it passes to the callback, so that the handles are guaranteed to be valid, but does it also block creation and destruction of pop-up windows? If not, there seems to be a race condition in between use of GetLastActivePopup() and processing of WM_CLOSE. The second and third scenarios seem to me to be cases where the programmer needs to fix the structure of the application.

  7. Raymond Chen says:

    EnumWindows blocks nothing. If it did, imagine the havoc you could cause by calling EnumWindows and then calling MessageBox in your callback.

  8. Waleri says:

    In other words, one cannot send WM_CLOSE blindly around. Problem is that MSDN didn’t warn about that at all in the description of WM_CLOSE. Q178893 mentions that WM_CLOSE may not terminate the process. IMHO, since it isn’t forbidden to send WM_CLOSE to a disabled window, applications should be able to handle this situation correctly.

  9. Ben Hutchings says:

    Raymond: So does that mean that any program that uses another thread’s window handles has unavoidable race conditions?

  10. Raymond Chen says:

    "Does that mean that any program that uses another thread’s window handles has unavoidable race conditions?"

    Indeed that has always been the case in Win32 if you do this without the cooperation of the target window.

  11. Ben Hutchings says:

    That’s kind of what I suspected. It makes me think it was a mistake to try to maintain the window messaging model in a preemptive multitasking environment.

  12. haroon says:

    Thanks for the interesting articles. I have read all seven. I have a situation which I think is arising from what you mentioned in part 6. However, I am not sure how to work around it. I have an MDI application in which MainFrame is also an event sink. To make things interesting, Modal dialogs are also invoked in these connection points. If MDI is displaying a modal dialog, I could get another modal dialog from connection point callback. This is fairly common scenario upon startup. Now the MDI has two modal dialogs. MainFrame is disabled and user can switch between the two modal dialogs. Is this is a valid behavior? i.e. having two modal dialogs at a time for one owner(MainFrame). Also, one of them, if closed last, can enable MainFrame. I am not sure how to ensure

    a) one modal dialog at a time, and

    b) MainFrame is only enabled after all the modal dialogs are gone.

  13. Raymond Chen says:

    This was already discussed in part 5.

Comments are closed.

Skip to main content