How can I tell whether a window is modal?


A customer wanted a way to determine whether a particular window is modal. They listed a few methods they had tried but found that it didn't work and asked for assistance.

As Eric Lippert is fond of saying, "First, write your spec." Until you know what you want, you won't know how to get it.

First, you need to define what you mean by a modal window. There are multiple competing definitions.

The customer decided that the definition of modal window they want is this one:

A modal window is a child window that requires the user to interact with it before they can return to operating the parent application, thus preventing any work on the application main window.

One thing you notice in this definition is that it talks both about windows and applications. You have a child window, a parent application, and even an application main window. This implies that a modal window must be in a different application from its parent. (If it were in the same application, then it vacuously does not prevent you from interacting with the parent application because it is the parent application.) But modality is a user interface concept, not a process management concept, so it's unclear why process considerations appear in the definition. End-users sitting in front of a user interface see windows, not processes. I'm going to assume that the use of the term application here is a mistake, and that all we're talking about is windows.

The second thing you realize from this definition is that it is describing something impossible. In Windows, child windows cannot be interacted with when their parent window is disabled. This definition appears to be using a common abuse of terminology, using the words child and parent instead of the more accurate but clumsier owned and owner. This common abuse of terminology rarely causes trouble among people with experience programming the Windows user interface, but it is often a source of confusion for beginners, which is why I try to use the precise terminology rather than the casual terminology. And this question was clearly asked by a beginner.

Another thing you notice about this definition is that it involves not two but three windows: The child window, the parent window, and the application main window. Consider the situation where you have an application main window (which is interactive), a secondary window (which is not interactive), and a tertiary window which is a child of by the secondary window with which the user must interact in order to return to operating the secondary window.

Application
main window
Secondary Solid borders represent interactive windows;
dotted borders represent non-interactive windows.
Lines connect children (below) to parents (above).
 
Tertiary

Is the tertiary window modal, according to this definition? I'm not sure. It is not clear to me whether the clause "thus preventing any work on the application main window" is an additional constraint or is merely elaborative. If the clause is an additional contraint, then the situation is not modal, because the application main window is still interactive. On the other hand, if the clause is merely elaborative, then the situation is modal, because the tertiary window prevents the user from interacting with the secondary window.

The fourth thing you realize from this definition is that it requires predicting the future. How do you know that the owner window will be available for use once you dismiss the owned window? Mabe the application does "if (time(NULL) % 2) make_parent_available();". (Perhaps we can call upon the graduates of the DePaul University with a degree in predicting the future to help us here.)

Even if the result doesn't depend on predicting the future, determining whether the window will re-enable its parent requires a level of code understanding beyond what can easily be achieved programmatically. (You would have to find the code in the other program and study it to determine whether it re-enables the parent window as part of its interaction. This can be hard to do by a human being with source code, much less by a computer program with only object code, especially if the object code is in an interpreted language, since you now have to reverse-engineer the interpreter too!)

No wonder the problem is so difficult: The spec uses imprecise terminology, is unclear on its criteria, and requires metaphysical certitude beyond the current level of scientific understanding.

Let's see what we can salvage from this definition. First, let's make the terminology more precise:

A modal window is an owned window that requires the user to interact with it before they can return to operating the owner window, thus preventing any work on the application main window.

Next, let's delete the clause whose meaning is unclear.

A modal window is an owned window that requires the user to interact with it before they can return to operating the owner window.

Finally, let's remove the part that requires predicting the future. Instead of describing future behavior (which is hard to predict), we'll make our requirements based on present behavior (which can be observed without the aid of a time machine).

A modal window is an owned window whose owner window cannot be interacted with.

The revised spec says that a modal window is an owned window whose owner is disabled. Bingo, there's your algorithm for detecting whether a window is modal. Once you have a good spec, the code pretty much writes itself:

BOOL IsModalWindowAccordingToThisParticularSpec(HWND hwnd)
{
 // child windows cannot have owners
 if (GetWindowStyle(hwnd) & WS_CHILD) return FALSE;

 HWND hwndOwner = GetWindow(hwnd, GW_OWNER);
 if (hwndOwner == NULL) return FALSE; // not an owned window

 if (IsWindowEnabled(hwndOwner)) return FALSE; // owner is enabled

 return TRUE; // an owned window whose owner is disabled
}

Mind you, this spec may still not be what you actually want. Consider the Notepad program. Type Ctrl+F to call up the Find dialog. This is a modeless dialog: The main window is still interactive. While the Find dialog is up, call up the About dialog from the Help menu. You now have the main Notepad window with two owned windows, an About dialog that will re-enable the main Notepad window when it is dismissed, and a Find dialog that will not.

Notepad main window A connector is solid if the owned window re-enables the owner, dotted if it does not. (Remember, whether the line is dotted or not cannot be determined algorithmically.)
   
About Find

According to our spec, which of these windows is modal? Does that match your intuitive sense?

Here's another case: From Notepad's Open dialog, type the name of a file that does not exist.

Notepad main window
 
Open
 
File not found

Which of these windows is a modal window?

Still unresolved is whether this is the right definition for the customer's needs. The customer never explained why they needed to identify modal windows, and once we gave them the Is­Modal­Window­According­To­This­Particular­Spec function, they never wrote back.

If they were trying to identify modal windows so they could try to close them, then in the File not found case above, they may try to close the Open window, when the correct window to close first is the File not found window, because you need to respect a window's disabled state.

Since the customer never wrote back, we will never know.

Comments (17)
  1. Mordachai says:

    Isn't this the sort of question that is almost certainly tied to doing something very wrong?

    Programs shouldn't need to determine things like modality… whether a given window is disabled or not, sure.

    This is the sort of question that begs to know "Why do you ask?!"  Surely the real solution is disabusing the customer of their basic misguided intentions…

  2. Frederik Slijkerman says:

    Interestingly, in your example, Windows itself also thinks that the Find window is modal in Notepad if it is active and the About dialog is also open. If you click on the main Notepad window, it flickers the Find window to indicate that this is the current modal window.

  3. Avi Shevin says:

    @Frederik

    I tried this on Windows 7.  Notepad flashes whichever of the windows has focus when you click on the main (editor) window.

  4. Joshua says:

    I'm willing to guess they were writing some window manager code where they somehow had this stupid assumption that the relationships were fully traceable.

    Or maybe all they needed was the easy case: Given this disabled window, find me an owned window that appears to be causing it to be disabled. This is what Windows does when you click on the disabled window.

  5. Falcon says:

    Raymond, I think you got the solid and dotted lines wrong in the Notepad-About-Find diagram.

    Or was this a sneaky trick to see if we were paying attention? :-D

    [Fixed, thanks. But yeah ummmmmmmmm it was a test! Yeah, that's the ticket! -Raymond]
  6. bcs says:

    From that it sound's like the correct answer is that being modal is not property of a window but of the code that "run" it. At a guess, what the end user was looking for is: "Will this window closing automatically re-enable it's owner?" If I'm reading correctly, the answer to that is "no, never."

  7. Joshua says:

    [I bet it picks the last active popup. -Raymond]

    Given the 15 year old outstanding bug about nested modal dialog boxes can be neatly explained by Windows using this API for the job, I'll bet it does too.

    FYI because somebody's going to ask, the workaround is to keep track internally and call SetFocus yourself in the WM_SETFOCUS message.

  8. Bjm says:

    Seems to me the correct answer is to stop disabling windows that I might want to use.

  9. MikeCaron says:

    @Joshua: How do you expect windows to be able to determine "an owned window that appears to be causing it to be disabled"? Disabling a window is a one-shot deal:

    EnableWindow(hWnd, FALSE);

    I strongly suspect that no one keeps track of this information, especially since that would require the win32 API to have psychic powers ("let's see… this position on the stack means we're being called from code that is associated with this particular window!")

    Rather, I bet it picks *some arbitrary* owned window and flashes that instead. See the Notepad example above.

    [I bet it picks the last active popup. -Raymond]
  10. Anonymous Coward says:

    @BCS: If you were to automatically close the About box by sending it the appropriate message, it will re-enable Notepad.

    @BJM: This. Just take the absurd situation in the example of this article. When you actually open Notepad and open the About and Replace dialogues, you are in the bizarre situation where you cannot enter text in the main window, but you can still edit the contents of the main window by interacting with the Replace dialogue.

    When you find yourself creating a modal dialogue, the first question you should ask yourself is: how can I do this without a modal dialogue.

  11. Anonymous Coward says:

    Also, as an afterthought, it was perfectly clear what the customer meant. No sane person could have misinterpreted it and the two-page drivel on how a moron might have read it is a waste of pixels. Maybe Raymond should sit in his own nitpicker's corner.

  12. Tim says:

    I believe – and I could well be wrong – that in the paragraph starting with "Even if the result doesn't depend on predicting the future…" all occurences of "parent" should read "owner" instead.

    @Anonymous Coward: If it is perfectly clear to you what the customer meant I challenge you to provide code that implements the appropriate algorithm.

  13. Anonymous Coward says:

    @Tim: Go and take up Reading Comprehension 101. I said it's perfectly clear what the customer means, not that the customer can get what he wants.

    The windowing system has no concept of modality. (And maybe for good reason because modal dialogues suck.) Every appearance of modality is hacked on and the application has to keep track of all the bookkeeping.

    And when the application or libraries the application calls screw up, you get erratic behaviour like in the case of Notepad where the About box is modal with respect to the main window but not with respect to the Replace dialogue. And the Replace dialogue… well, we've already talked about that. The reason that in this case it's hard to say if the windows are modal or not is because there is a bug in the software. It makes no sense to even ask if a dialogue is modal when the machinery behind modality breaks down.

  14. @Anonymous Coward: I completely agree (with your comment regarding Raymond's pedantic rhetoric).  If he replied to the customer in a similar vein I'm not at all surprised that they "never wrote back"!

  15. OCD says:

    @Anonymous Coward

    The point of the "two-page drivel", is to carefully de-construct what the seemingly obvious concept "modal window", actually means. By carefully thinking through this concept, it becomes clear what "modality" really is, and the answer to the initial question is obvious. The point of this was to show how a little thought would have allowed the customer (and people like yourself) to answer that question themselves. That you are somehow offended by long detailed explanations suggests that you would likely go the ignorant route yourself, and ask the unnecessary question instead of thinking it through. Raymond seems to be on a quest to try and help people help themselves, but it will do nothing for the arrogant who are determined to remain ignorant.

    @Richard

    Anonymous is clearly a troll (who I have just given a nice large meal), but it is disappointing that you would side with such bile. Personally I would think twice before publicly criticising a highly respected blogger/developer when not hiding behind an anonymous persona.

  16. Smitty says:

    "This definition appears to be using a common abuse of terminology, using the words child and parent instead of the more accurate but clumsier owned and owner."

    Perhaps this person has been using the Windows API for a long time, and is used to seeing API calls like:

    HWND WINAPI GetParent(

     __in  HWND hWnd

    );

    with the (mostly confusing and almost completely useless) description – note the almost completely unhelpful use of OWNER and a PARENT in the same function description:

    If the window is a child window, the return value is a handle to the parent window. If the window is a top-level window with the WS_POPUP style, the return value is a handle to the owner window.

  17. Nick says:

    While the bile from Anonymous is certainly unwarranted, and I respect Mr. Chen's expertise (Wouldn't read this blog otherwise!) it really does come off as "The customer asked us a simple question, and I wrote a 1000 word pedantic essay instead of answering it."

    [Duh, the customer didn't get the 1000-word essay. The 1000-word essay was written for the blog to illustrate the point: "First write your spec." And I walked through the process of writing the spec in painstaking detail to show how it's done. -Raymond]

Comments are closed.

Skip to main content