Date: | February 18, 2005 / year-entry #42 |
Tags: | code;modality |
Orig Link: | https://blogs.msdn.microsoft.com/oldnewthing/20050218-00/?p=36413 |
Comments: | 26 |
Summary: | From the end-users' point of view, modality occurs when the users are locked into completing a task once it is begun, with the only escape being to cancel the entire operation. Opening a file is an example of a modal operation: Once the "Open" command has been selected, users have no choice but to select... |
From the end-users' point of view, modality occurs when the users are locked into completing a task once it is begun, with the only escape being to cancel the entire operation. Opening a file is an example of a modal operation: Once the "Open" command has been selected, users have no choice but to select a file for opening (or to cancel the operation). While attempting to open a document, the users cannot interact with the existing document (for example, scroll it around to look for some text that would give a clue as to what file to open next).
From a programmer's point of view, modality can be
viewed as a function that performs some UI and doesn't
return until that UI is complete.
In other words, modality is
a nested message loop that continues processing
messages until some exit condition is reached.
In our example above, the modality is inherent in
the Note that these concepts do not necessarily agree. You can create something that is UI-modal—that is, does not let the user interact with the main window until some other action is complete—while internally coding it as a non-modal function. Let's code up an example of this behavior, to drive the point home. As always, start with our scratch program. #include <commdlg.h> HWND g_hwndFR; TCHAR g_szFind[80]; FINDREPLACE g_fr = { sizeof(g_fr) }; UINT g_uMsgFindMsgString; void CreateFindDialogUIModally(HWND hwnd) { if (!g_hwndFR) { g_uMsgFindMsgString = RegisterWindowMessage(FINDMSGSTRING); if (g_uMsgFindMsgString) { g_fr.hwndOwner = hwnd; g_fr.hInstance = g_hinst; g_fr.lpstrFindWhat = g_szFind; g_fr.wFindWhatLen = 80; g_hwndFR = FindText(&g_fr); } } } void OnChar(HWND hwnd, TCHAR ch, int cRepeat) { switch (ch) { case ' ': CreateFindDialogUIModally(hwnd); break; } } void OnFindReplace(HWND hwnd, FINDREPLACE *pfr) { if (pfr->Flags & FR_DIALOGTERM) { DestroyWindow(g_hwndFR); g_hwndFR = NULL; } } // Add to WndProc HANDLE_MSG(hwnd, WM_CHAR, OnChar); default: if (uiMsg == g_uMsgFindMsgString && g_uMsgFindMsgString) { OnFindReplace(hwnd, (FINDREPLACE*)lParam); } break; // Edit WinMain while (GetMessage(&msg, NULL, 0, 0)) { if (g_hwndFR && IsDialogMessage(g_hwndFR, &msg)) { } else { TranslateMessage(&msg); DispatchMessage(&msg); } }
This is an unexciting example of a modeless dialog;
in our case, the Find dialog is displayed
when you hit the space bar. Observe that you can click
back to the main window while the Find dialog is up;
that's because the Find dialog is modeless.
As is typical for modeless dialogs, dispatching its
messages is handled in the main message loop with
a call to
the We can turn this into a UI-modal dialog very simply: void CreateFindDialogUIModally(HWND hwnd) { if (!g_hwndFR) { g_uMsgFindMsgString = RegisterWindowMessage(FINDMSGSTRING); if (g_uMsgFindMsgString) { g_fr.hwndOwner = hwnd; g_fr.hInstance = g_hinst; g_fr.lpstrFindWhat = g_szFind; g_fr.wFindWhatLen = 80; g_hwndFR = FindText(&g_fr); if (g_hwndFR) { EnableWindow(hwnd, FALSE); } } } } void OnFindReplace(HWND hwnd, FINDREPLACE *pfr) { if (pfr->Flags & FR_DIALOGTERM) { EnableWindow(hwnd, TRUE); DestroyWindow(g_hwndFR); g_hwndFR = NULL; } } Notice that we carefully observed the rules for enabling and disabling windows. When you run this modified program, everything seems the same except that the Find dialog is now modal. You can't interact with the main window until you close the Find dialog. The Find dialog is modal in the UI sense. However, the code is structured in the non-modal manner. There is no dialog loop; the main window loop dispatches dialog messages as necessary. One typically does not design one's modal UI in this manner because it makes the code harder to structure. Observe, for example, that the code to manage the dialog box is scattered about and the management of the dialog needs to be handled as a state machine since each phase returns back to the main message loop. |
Comments (26)
Comments are closed. |
Even when modal windows seem appropriate they can really hurt usability. Every few months I run into this with Outlook. I get an email saying "Your new email account is ready, here’s the username and password." My first instinct is to open up the Tools, Accounts, New dialog and try to copy/paste the information from the message to the dialog. No can do, the dialog is modal and Outlook’s message window is disabled. The Office Clipboard stacks copies/pastes and might be useful, but it is not available in the dialog!
Correct me if I’m wrong – but isn’t this the way to handle fakemenu style popups?
It is "a" way, but hardly "the" way. Not even the fakemenu sample itself uses this technique.
Maybe part 2 will be real modal dialog, like the search in the last usuable MSDN viewer (Oct 2001). It has a cancel button that seems to store the cancel message till the dialog finishes (never been sure the point of this cancel).
Actually, isn’t this another perfect use for fibers or threads? You can have your modality and a single message loop (which is sometimes important) at the same time.
The code that provides the logic backing the UI runs on a fiber or thread and can wait until the dialog box state becomes appropriate before continuing. So its easier to "hide the state machine."
-MYG
I’d like to see this used more often…
For example, if there’s a dialog box in Internet Explorer (invoked by user and forgotten, or sometimes invoked by the program), then any links clicked from other programs that would normally open in IE are simply vanishing in thin air.
If anyone watched last Apple keynote, the same thing happened to Steve Jobs previewing OS X Tiger in front of many people — iPhoto was stuck with some sort of dialog box and ignored import functions from another program.
Assuming that the code structure is fine, is it a UI sin to make every possible thing modeless (i.e. Open and About windows too) unless an algorithm absolutely requires modal?
It is generally understood that any modal operations are a "bad" thing in UI design, so making as much of your program as modeless as possible would actually be a good thing. I think we are simply stuck with certain level of modality in Windows, but UI purists would probably argue that.
> One typically does not design one’s modal UI
> in this manner because it makes the code
> harder to structure.
*One* typically doesn’t. But, if I’m not mistaken, classic versions of Borland Delphi and C++ Builder do implement modal dialogs exactly this way. In fact, they aren’t even *dialogs* in the strict sense; they are not based on a dialog box template and do not use DialogBox or DialogBoxIndirect.
"No it isn’t. It is silly blanket statements such as this that produce some of the worst UI ever created by man."
What I stated is correct – it is generally accepted amongst UI experts that modality is bad. You may disagree with that, I’m by no means an UI expert but all the research I’ve done on this topic in the past 10 years generally comes to the same conclusion.
"Use the right thing for the right task."
What they would argue is that you haven’t thought the task through correctly from the user’s point of view if your solution is modality. Again, don’t shoot the messenger… :)
http://www.datanation.com/fallacies/anon.htm
BTW, I have been doing UI design for 20 years along with the research required to do a good job.
But like you, stating such is just another logical fallacy.
There is nothing "bad" about modal dialogs. However, they can be used inappropriately and often are. For reasons already stated (i.e. ease of implementation), they are commonly used when a modeless solution is better. But that still doesn’t change the fact that there are many instances where they are the right decisions. I think we would all be very hard pressed to find an application of significant complexity that are 100% modeless. Obviously such applications can be created since all you would have to do is avoid the situations where modal is a better choice.
http://www.amazon.com/exec/obidos/tg/detail/-/0764526413/qid=1108846080/sr=8-1/ref=pd_bbs_1/002-2549661-9035239?v=glance&s=books&n=507846
http://www.cooper.com/content/company/about_cooper.asp
It is pretty easy to see why modality is considered bad in UI design. Take Ray’s example from the first paragraph above: the only reason Open Dialog has been made modal is to help us, programmers, from worrying about minutia of interface management. Arguing that a modal Open Dialog is in some way better than modeless one can be done from the programmer’s perspective, but the user would obviously prefer to be able to switch from window to window as they please.
Are there examples of bad modeless design out there? You bet! That does’t mean that all modeless design is bad. But there is a lot more bad modal design:
http://www.rha.com/ui_hall_of_shame.htm
Scroll to the Quicken example half way down the page – if you think that is uncommon think again. I just had to deal with modality from hell the other day as I was changing some settings for my display adapter. I think I had 4 modal dialogs open one over the other, average user would definitely get lost long before then. There are many similar examples in Outlook, Word, etc.
"But that still doesn’t change the fact that there are many instances where they are the right decisions."
Hey, I use them all the time. But I think ideally every modal scenario has a better modeless implementation. It just may be a lot more costly to implement.
"I think we would all be very hard pressed to find an application of significant complexity that are 100% modeless."
Agreed! This is all theoretical.
Just for clarification.
What I am arguing about is how the statement is worded.
"It is generally understood that any modal operations are a "bad" thing in UI design, so making as much of your program as modeless as possible would actually be a good thing."
You are basically staying that people shouldn’t use modal windows without giving them the knowledge of when a modal is good and when it isn’t. It leads to mindless striving towards a goal that people don’t understand why it is a good goal, but much worse, they don’t understand the limitations of the goal. Thus you end up hurting the end user by forcing a workflow on them that isn’t optimal.
If we are talking about a new kid just out of school, I am all for giving them solid rules. However, as people gain the experience and understanding of the limitations of the rules, they should be allowed the freedom to decide for themselves what is right and what is wrong.
Gotos are not evil, they are just grossly inappropriate. If you don’t believe me, read Dijkstra’s paper on gotos where he discusses a few of the cases where gotos solve problems well. Knuth also has a very interesting paper on the subject where he purposely leaves the reader not knowing if he is in favor or against gotos.
Give people the knowledge instead of rules. Let them decide which is best.
I think you are discussing this from a programmer’s point of view. My statement is in the realm of user interface design – I don’t know of any UI expert (someone who has done research and papers on the subject) that advocate modal design. If you know any please let me know. Many books have been written on the subject so I can’t really impart much wisdom in these posts, just summarize it.
I can’t say that there’s no legitimate application of a modal dialog box; this is one of those arguments over practical technique wherein no stance on the issue can be supported formally.
However, I can propose an alternative to modal dialog boxes that would probably work in most situations.
Suppose I have a window that contains a list of icons (think along the lines of Explorer). Now, suppose the user’s interactions with the icons will result in a state change somewhere else in the system (e.g. deleting an icon deletes a file, moving an icon moves a file, etc). Many of these state-altering interactions occur within the container window. Some occur within a dialog box (e.g. the "Properties" dialog).
Now, if the user invokes the "Properties" dialog box on an icon, and prior to dismissing the dialog deletes the icon, what happens? Is the user suddenly setting the properties of a non-existant icon?
This type of problem can be generalized: there are some dialogs that only make sense within the context of a particular state. If the relevant state can be altered while the dialog is present, we enter the realm of uncertainty.
So when we encounter a situation where this might occur, we often use modal dialog boxes. Why? Simple: by making the dialog modal, we prevent the user from changing the state out from under us. We have, in effect, put the underlying system into read-only mode.
Except that with modal dialog boxes, you can’t even read, necessarily. You make the whole thing a non-issue by rendering the underlying window useless.
So instead of using a modal dialog box, why not just disable the icon-modifiers in the underlying window? This makes the window read-only, while still allowing the user to actually read the contents of the window.
Be warned, however: this alternative is dangerous when incorrectly applied. One of the best ways to confuse a user is to make changes in the UI that are not an obvious, direct result of a user’s actions. Thus, if you decide to make the underlying window read-only, make it obvious that you have done so, and why.
In the interest of better understanding this design issue, I am interested in hearing about flaws to the read-only approach, or scenarios where it would not work.
I guess making underlying window "read only" is implementing modality in a different way. Result is the same – user should not be able to change things while properties are visible. The only difference I see is that user will be able to switch back to main window. That may lead to a confuse – a user may try to delete/move/whatever an icon but system will deny it, which will result a complain from the user "damn thing doesn’t work".
Second problem with modeless design is that application should keep track of which windows are opened, otherwise you may end with dozens Help/About windows on screen.
Asking me, modal is good when used properly
This is why I was careful to mention that it must be made clear to the user that the window is in a read-only state, as well as why it is in this state.
The notion that modal dialogs are "good when used properly" is a self-satisfying statement. I believe I can elaborate on it without losing any meaning.
"Modal dialogs are good when they are the best solution to a problem." This begs the question: are there any problems for which a modal dialog is the best solution? If we are using modal dialog boxes to lock us into an underlying state, then I believe that a read-only window is a superior choice, since it allows the user to look back to the window for reference if they need to (Chen touched on this in the original post).
But, once more, this can confuse the user unless it’s obvious what has happened. It looks like I need to be more explicit and provide an example design.
Consider Word’s table "properties" dialog (Tom Saxton was my calculus teacher in h.s.). Instead of using a modal dialog, I propose that the properties are displayed in a pane to the side of the document. This makes it impossible for the user to lose the dialog in the z-order, and allows the user to see the properties and the document at the same time without moving windows around.
To make it blindingly obvious to the user that the window is in read-only mode, and that this mode was entered because of the properties pane (it’s a pane now, remember?), we might have an alpha-blended image over the document that says, in great big words, "READ ONLY," followed by a large-print statement about how the user needs to dismiss the pane. If we want to get really pedantic, we might even include an option to disable this message.
And there we have it: the underlying state won’t change out from under the dialog, but the user can still read the document. When the dialog is dismissed everything goes back to normal. We’ve introduced a big, obvious sign that tells the user that we’ve gone read-only and -why- we’ve gone read-only.
Incidentally, I have observed users (older family members in particular) who get confused by modal dialog boxes. I can see why this is: you see, with a modal dialog box, the very presence of the dialog alters the behavior of another window that is not obviously related. Worse, no explanation of this correlation is provided to the user.
From where I stand, modal dialog boxes are starting to look pretty poor in the general case.
"What I stated is correct – it is generally accepted amongst UI experts that modality is bad."
As others have mentioned, this is not necessarily true. Modes have often been misued by program designers and there are many examples of where their use has caused problems. However, modes in general aren’t bad. It’s their incorrect use that is bad.
Ask the question, "what is wrong with modes?" Many UI experts will tell you that modes cause trouble when a user is placed in a mode and there is no feedback to indicate that they are in a mode. The typical scenario here is that the user is unaware of being in a mode and then tries to do some action that is usually performed in the normal "non-mode" state and either the action is not allowed in the modal state, or worse, produces a different result in the modal state. Another problem with modes arises when the user doesn’t know how to get out of a mode.
Good uses of modes are all around us. Many painting and drawing applications use a palette of tools, where you select, say the pencil tool, and you draw with a pencil. This is a mode. Because the user is given good feedback (e.g., cursor looks like a pencil) and the user can easily get out of the mode (e.g., select another tool or click on a menu item), this is not bad.
Also, consider the use of a scroll bar or menu. These all use temporary modal interaction. For example, when you click on the thumb of a scroll bar and move the mouse to scroll, you are essentially placed in a mode. Notice how other operations (e.g., pressing alt-F to access a File menu) do not work while scrolling. Again, these aren’t considered bad because the user is still in direct control – they can easily get out of the mode by simply releasing the mouse or, in the case of a menu, clicking elsewhere to dismiss the menu.
Getting back to modal dialogs. Generally, problems arise here when the user is required to answer some question or perform some action that requires information from another area of the program that has been made inaccessible by the use of the modal dialog. In such cases, often the user is forced to cancel the dialog, go back to the area of the program to find the information, and then attempt the original operation again which brought up the modal dialog. Obviously, such a scenario is bad. But, this is usually due to poor design of the modal dialog and poor workflow design. By redesigning the workflow or dialog, such problems can be avoided. Modal dialogs are not bad in themselves.
What the hey, I haven’t seen the one discussion on this topic that should have been said. Everyones arguing on the semantics of the issue, but use them everyday, and seem to have forget how good a model dialog is.
Now before you jump all over me, for a blanket statement, think of this example, you use it everyday, and I wouldn’t have it any other way. When windows starts up for the first time, you sometimes want to set it to ask you to log in, well guess what that is a model dialog, you are required to enter a password and name to beable to continue in a new mode.
A GOOD example of a model dialog, and it’s use would be just that, if you wanted to verify a user, than you would bring up a model dialog and have them enter their user information, what good would be the dialog if they can do something else, even anything else. Once you know they are not who they say they are, your program can handle that, or if they are verified your free to do what you want.
MikHaven
PingBack from http://www.adrianmccarthy.com/blog/?p=52