Gentle reminder: On a dialog box, do not give OK and Cancel accelerators


I know most of you know this, but I'm going to say it for the record. When you have a dialog box with an OK and/or Cancel button, do not give the keys accelerators. In other words, simply write

    DEFPUSHBUTTON "OK", IDOK, ...
    PUSHBUTTON "Cancel", IDCANCEL, ...

The dialog manager already has those buttons covered. The hotkey for the OK button is Enter (since it is the default pushbutton), and the hotkey for the Cancel button is ESC (since its ID is IDCANCEL).

Note of course that during the lifetime of a dialog box, the default pushbutton may change, but the principle still stands: Do not give the OK button a keyboard accelerator.

Oh, and while you're there, don't forget that the recommended minimum size for pushbuttons is 50dlu by 14dlu.

Comments (34)
  1. ac says:

    Its not like it breaks the dialog if you have "&OK", its harmless and pointless

  2. Michael Dwyer says:

    I’m sorry if I’m being obtuse, but what’s a ‘dlu’?  I assume it means something like pixels adjusted for DPI?

  3. pingpong says:

    @Michael Dwyer: dlu == dialog unit.

  4. Dan McCarty says:

    Speaking of dialog accelerators, this seems like a good place to mention an increasing Windows problem these days: focus-stealing dialogs.

    With many apps open some background app will present a dialog.  Usually Windows recognizes the situation and blinks the app’s button on the Start bar.  But sometimes the apps steal focus.  Meanwhile, if I’m typing in another window a dialog pops up and since I have several characters already buffered in the space bar will inadvertently hit the OK or Cancel button when it gets focus.

    Explorer is also an offender, but in a different way.  A feature of explorer is that the copy/paste/delete status dialog is non-modal so you can work within the window during a copy/paste delete operation.  But since the dialog can take several seconds to pop up you can hit space to highlight a file just as the dialog appears, canceling the operation.  Or you can hit space right as an "Overwrite?" confirmation dialog appears, frequently choosing the option that you didn’t want.

    I don’t know what the solution is; it seems like a complex problem.  Prevent WM_KEY* messages from going to a window within the first x milliseconds of focus?  That would probably penalize users who are fast.

  5. Michael Dwyer says:

    1 dlu width = 1/4 the average width of the system font

    1 dlu height = 1/8 the average height of the system font

    So the minimum button size is approximately equal to a block of text 12 characters wide and two characters high in the system font.

    Neat!  Thanks for the lead.

  6. asmguru62 says:

    The ENTER and ESC works in a dialog even if dialog has neither OK or Cancel buttons. So cool!

  7. John says:

    Dan:

    Tell me about it.  There is nothing more infuriating than a dialog / application stealing focus when you are in the middle of typing.  My absolute favorite is the Windows Update notification asking you if you want to reboot the computer (every 5 seconds, it seems).  The "Yes, restart my computer now" button has the focus and is the default button.  I’m pretty sure it gives applications a chance to save their documents, so it could be worse.

  8. It’s very easy.

    The O/S should never allow a program to steal focus.

    KDE allows this to be set, for instance. Probably GNOME too…

  9. Alexandre Grigoriev says:

    Speaking of applications stealing focus, I only know one. Yes, it’s Internet Explorer. It insists on popping to foreground at least three times during page load. Or is it embedded Flash objects?

    Anyway, The Great War of SetForegroundWindow still goes on. First strike was made by WinME, but the enemies regrouped and are marching ahead. Including enemies within.

  10. Dan says:

    50dlu by 14dlu?  Interesting.  .NET has a default pushbutton size of 75 pixels by 23 pixels… but they don’t quite match up (if you assume 1dlu is 1.5px (with the default DPI) you get 75×21 pixels).

    But then again I suppose you’re not really supposed to match them up, as the entire point is they’re not tied to exact pixel measurements.  Still, .NET doesn’t seem to have any other measuring method other than pixels which would seem to make it difficult to adjust to higher DPIs (or does it do that automagically?  I should check as it probably would make all my programs look awful).

  11. @Tom: I’ve not seen such an option on GNOME, and I very much wish I did. The number of times some stupid GNOME dialog has come up, or the damn thing has let a single window continually steal focus while I’m working in another one…

    Probably best for me to stop now; you don’t want to get me started on that horrid, horrid environment.

  12. Nar says:

    simply write

    DEFPUSHBUTTON "OK", IDOK, …

    PUSHBUTTON "Cancel", IDCANCEL, …

    Hopefully you don’t mean that literally. Most times the statement posited or the question asked deserves a proper answer so the dialog buttons alone make some sense to the user, who would otherwise have to scrutinize the text to find out what they do. Here, let me:

    For a better ‘Enter Network Password Dialog’ simply write

    DEFPUSHBUTTON "Logon", IDOK, …

    PUSHBUTTON "Cancel", IDCANCEL, …

  13. David Lanterhorn says:

    Excuse me for not getting it, but I don’t understand why the accelerators are considered a bad idea? The more accelerators the better, right?

    And isn’t a &C accelerator more discoverable than the ESC button? (Note that people who started using computers after Windows 95 aren’t really used to using the ESC button).

  14. IUnknown says:

    @David Lanterhorn:

    They probably know how to press the right (or left) arrow key or tab and spacebar though. (Besides using the mouse, but that’s not the point.)

  15. Leo Davidson says:

    "The O/S should never allow a program to steal focus."

    If there wasn’t a mechanism to allow another program to take focus then you could not have two programs which appear to work as one, which would be very annoying in some places.

    The current mechanism isn’t perfect but some kind of mechanism is needed, I think.

  16. StopAsking says:

    When I get the random dialog box with the usual buttons (OK, Cancel, Reboot, etc..) and I just don’t want to attend to the Q I do what billions do – hit the X in right corner. The Windows reboot annoyance just doesn’t give up though, so one have to resort killing the process. But hey! Maybe that triggered a restart… Dang!

  17. Alexandre Grigoriev says:

    "goto *i;"

    I’m not sure what programming language it is. Fortran? It’s definitely not C(++).

  18. Aaargh! says:

    "The Windows reboot annoyance just doesn’t give up though, so one have to resort killing the process. But hey! Maybe that triggered a restart… Dang!"

    The solution for that is ‘simple’, click on the window menu and select ‘move’. Then use the cursor keys to move the window to the bottom-right of your screen, you can move is so far only a few pixels remain. As long as the current dialog hasn’t been closed a new one won’t pop up.

    "When you have a dialog box with an OK and/or Cancel button,(…)"

    Even better, of course, is not to have dialogs with OK/Cancel buttons. Have dialogs with buttons that actually describe what the button does.

  19. Vandicov says:

    @ac: "&OK" damages consistency, which hurts usability. On some dialogs you want to use O as a legitimate accelerator. So on some dialogs, it’s OK, and others it’s not. It’s better for users to learn that pressing Enter (and Escape) is the right way.

  20. Peter says:

    Alexandre: I agree.

    Personally I don’t think I’d trust that; in my experience calling some infinitely recursive function works well in Windows. It’ll overflow the stack in a small part of a second and the program will be immediately terminated with no feedback to the user.

    Plus, putting silliness like this into production will give Raymond something to blog about in five years time ;-)

  21. steveg says:

    For the record you can put multiple buttons on a form with the same identifier — imagine a situation where some software from a long-gone vendor says "your 30-day trial period expired 1/1/1993" and it has Cancel and a disabled OK. Solution: edit the resource and add a second ID_OK button.

    (Almost but definitely not related: why doesn’t Ctrl+Tab work in tab dialog boxes in Vista anymore? Has anyone else noticed this? I see it in a C# 2.0 app, not sure if that’s relevant or not).

  22. a sweet thing says:

    If you really must abort your program, try something like this:

    int *i=0;

    *i = ~0;

    goto *i;

    Even if the user got something like "Access violation! Abort/Retry/Ignore?" on the second line and chose to ignore, address 0 probably doesn’t contain a valid instruction. There *might* be a RET there though, in which case this function does nothing. But if somehow the write operation did succeed(???), the CPU would probably barf and the OS would swiftly eliminate the process (perhaps with a little leakage).

  23. Dean Harding says:

    "Almost but definitely not related: why doesn’t Ctrl+Tab work in tab dialog boxes in Vista anymore?"

    Works for me (for example, right-click on the taskbar and choose Properties… it works in that dialog)

    Perhaps it’s just that particular program?

  24. a sweet thing says:

    Erm, whoops, that last comment wasn’t meant for this article :S I always open the articles in new tabs, and had accidentally closed one. I must’ve then got them mixed up.

    And goto *i; compiles fine in GCC, haven’t tried msvc yet. I know it doesn’t conform to the ANSI C89/C99 standard, but it’s better then inline asm.

  25. Jax184 says:

    Following up on the focus stealing comments…

    I think the whole focus stealing thing is actually a symptom of a bigger problem. It seems to me that most software companies assume the sole reason the end user even owns a computer is to run their Expensivesoft yak waxer 2008 deluxe edition. Such software often installs a desktop shortcut, a quick launch shortcut, a shortcut pinned to the start menu, an internet explorer tool bar, adds itself as the default program for opening half the files on the computer and launches at startup. What do you mean you just want to check your email?

    Unfortunately this problem seems to be one with an even more elusive solution. You can’t write a windows update that makes companies realize they’re not the center of the universe.

  26. SuperKoko says:

    @Leo Davidson:

    "

    If there wasn’t a mechanism to allow another program to take focus then you could not have two programs which appear to work as one, which would be very annoying in some places.

    "

    With a correctly-configured WindowMaker (or KVM, I guess), popup windows, independently of their source (same process or different process), get the top-level Z-order, but don’t get the keyboard focus until the user explicitly focus them with ALT+TAB or a simple click.

    So, an extra click is required, but, my everyday experience tends to prove that it’s worth. Of course, it can be disabled as you wish.

    @Alexandre Grigoriev:

    I guess that’s the non-standard GCC "labels as values" extension.

    http://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html

    Anyway, that’s off-topic…

  27. Igor Levicki says:

    There are some Windows dialogs where Esc and Enter simply do not work. I guess that someone forgot to add if (!IsDialogMessage(&msg)) in there but I might be wrong. When you don’t have a mouse connected it is a PITA.

    My opinion is that Enter, Esc and Spacebar should be banned from dialog accelerators and replaced by Alt+<key> combination simply because stealing focus problem people mention so often would not result in wrong dismissal of a dialog asking you to confirm some destructive action. Therefore I actually prefer &Ok and &Cancel.

  28. pingpong says:

    "If you really must abort your program, try something like this:

    int *i=0;

    *i = ~0;

    goto *i;"

    Just once? I thought it must be executed at least two times (four on dual-core CPUs).

  29. Hebbje DiWeer says:

    Hey Igor! I, for one, would be grateful if you crawl back into whatever snakehole you came out of. No offence.

    Responding to user interaction with a dialog box is ok. The notification area and balloons are for when something really bad or really great happens without user interaction. Information bars are for other things that don’t neccissarily require a response from the user.

    For those non-conformant programs, you can use terminal services (with FUS perhaps) to condemn them to another desktop.

  30. Centaur says:

    Do not give OK an accelerator — unless the main point of the dialog is a big multiline edit box. In which case, an accelerator is very welcome.

    I would maybe even go as far as implementing Ctrl+Enter as an OK shortcut for every dialog, independent of which other button is focused or whether the focus is in a multiline edit or another control that wants Enter for itself.

  31. spangle says:

    Hebbje DiWeer: I found Igor’s comment insightful. Why don’t you stop trolling and crawl back into whatever hole you came out of?

    A little bit off topic, does anyone know the name of that "restart windows now" process that pops up when you update?

  32. Who uses keyboard accelerators and shortcuts?

    You do, and I do, and everyone who reads this blog probably does.

    No one else does.

    I have watched a lot of people interact with dialogs and web forms. They reach for the mouse and click on a field, type something, reach for the mouse and click on the next field, type something, reach for the mouse and click the OK/Submit/Whatever button.

    You can tell someone, in your nicest tone of voice, "Try hitting the Tab key to move to the next field, and Enter when you’re done." They won’t do it. It’s over to the mouse to click, every time.

    That’s why every browser has a "go" button next to the address bar, even if there wasn’t one there in a previous version. It’s why Firefox 2 has a magnifying glass icon next to the search box. It’s the mouse or nothing.

    (Do I need a nitpicker’s corner on this comment? Yes, of course I’m exaggerating. But not by much!)

  33. slimpo says:

    @spangle: probably wuausrv or something. Try using process explorer (drag the target over the dialog).

  34. Triangle says:

    Spangle: C:WINDOWSsystem32wuauclt.exe. But you can just change the update settings to do nothing about updates. That’s what I do; every month or so whenever I have a free moment, I turn it on, install all the updates and restart however many times is required to appease it. Then I disable it again. Far less painful that way.

Comments are closed.

Skip to main content