Why don’t context menus respect the UI state for keyboard accelerators?


The WM_CHANGE­UI­STATE message lets you manipulate the UI state of a window, which controls whether keyboard accelerators and other UI affordances are shown. Let's use it to try to control the mnemonics of a window. Start with the scratch program and make these changes:

BOOL
OnCreate(HWND hwnd, LPCREATESTRUCT lpcs)
{
  CreateWindow(TEXT("button"), TEXT("&Button!"),
    WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
    0, 0, 200, 50, hwnd, (HMENU)100, g_hinst, 0);
  return TRUE;
}

void OnContextMenu(HWND hwnd, HWND hwndFrom, int x, int y)
{
  auto hmenu = GetSystemMenu(hwnd, false);
  TrackPopupMenu(hmenu, TPM_RIGHTBUTTON, x, y, 0, hwnd, nullptr);
}

void OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
{
  if (id == 100 && codeNotify == BN_CLICKED) {
    if (SendMessage(hwndCtl, BM_GETCHECK, 0, 0)) {
      SendMessage(hwnd, WM_CHANGEUISTATE,
                  MAKELONG(UIS_CLEAR, UISF_HIDEACCEL), 0);
    } else {
      SendMessage(hwnd, WM_CHANGEUISTATE,
                  MAKELONG(UIS_SET, UISF_HIDEACCEL), 0);
    }
  }
}

// Add to WndProc
    HANDLE_MSG(hwnd, WM_COMMAND, OnCommand);
    HANDLE_MSG(hwnd, WM_CONTEXTMENU, OnContextMenu);

This program lets you toggle the checkbox to turn keyboard cues on and off. The checkbox itself has an accelerator so you can verify the state. if you right-click anywhere or hit Shift+F10, the system menu appears as a context menu. (Note that this program doesn't try to position the context menu anywhere interesting when invoked from the keyboard.)

Enable keyboard cues with the checkbox, and then right-click. Or disable keyboard cues and hit Shift+F10, The menu shows up and ignores your keyboard cues settings, instead taking its keyboard cue state based on whether you used the mouse or keyboard to display the menu. Same thing happens if you open the system menu by right-clicking the title bar or hitting Alt+Space.

What's going on? Why isn't the menu picking up the UI cue state?

Because the menu is in a separate top-level window tree, and keyboard cues apply to a top-level window tree.

Menus, like dialog boxes, initialize their UI state based on the last input event.¹ So they will show keyboard cues if you invoked the menu from the keyboard, and won't show them if you invoked the menu from the mouse.

¹ The user's keyboard cues preferences override this logic. If the preferences indicate that keyboard cues should always be shown, then they are always shown.

Comments (22)

  1. skSdnW says:

    “Because the menu is in a separate top-level window tree” that might be the technical reason but I assume the UI team had a discussion about this when the feature was added. The menu knows the owner window and could easily ask it if inheriting the state was the intended design.

    1. I called this out in the next paragraph: “Menus, like dialog boxes, initialize their UI state based on the last input event.” It is by design.

  2. DWalker07 says:

    A former boss of mine would call all of this “implementation details”. It explains why something doesn’t work in the way you would expect, but it violates the “principle of least astonishment”.)

    But it’s good to know nevertheless.

  3. Adrian says:

    I find the UI state much less consistent in Windows 10 than Windows 7. For example, using the keyboard, open the Start menu, type `regedit`, and hit Enter. The Windows 10 UAC prompt does not have the mnemonics for Yes and No marked as it did in Windows 7. Worse, pressing Alt doesn’t show the mnemonics. You have to press and release Alt (and then press it again if you want to use the mnemonic).

    I’d love to see the data that showed why it was even worthwhile to introduce all the complexity (and inherent inconsistency) of UI state. What was wrong with always showing the mnemonics?

    1. Randomly underlined letters scream “This operating system was designed by computer nerds for computer nerds. (Regular people should just get a Mac.)” Also, what would be the point of underlining keyboard accelerators on a keyboardless system?

      1. Brian_EE says:

        What’s the point of menus on a keyboardless system? People who use keyboardless systems only know how to communicate with emojis and pictures of themselves with things (erroneously) called filters.

        1. Antonio Rodríguez says:

          Not exactly. Many people use “keyboardless systems” to do useful work (data collecting apps, medical and other sectorial apps, email and documents on-the-go, etc.). And I think that, given that their use is more critical than that of the average instagrammer, they should be taken seriously when designing an UI. And remember that all the pioneer “keyboardless systems” (Apple Newton, Psion Organizer, Palm OS, Windows CE…) implemented some sort of menu bar.

          Anyway, I think the decision of wether to underline keyboard accelerators on the UAC confirmation dialog should be made depending on wether the device is in tablet mode or not. But I don’t know if that would be possible (the UAC dialog shows in an isolated desktop, so maybe it can’t query the tablet mode status).

          1. Brian_EE says:

            I’m used to having to use <ticc> [1] on Ars. Didn’t think I would need it here.

            [1] ticc == tongue in cheek comment

          2. Antonio Rodríguez says:

            As the tittle text of xkcd.com/301 says: “Fun game: try to post a YouTube comment so stupid that people realize you must be joking. (Hint: this is impossible)”. Because of that, it’s advisable to always add an emoticon :-) .

        2. Yukkuri says:

          Thanks for relegating my work on touchscreen based POS systems to the status of pointless frippery.

          1. anai says:

            … memories of “fat finger” UI work and “there is no right mouse click” (days before ‘long press’), and as to “hover over” helptext….

      2. JAS says:

        Not only did you obfuscate the user interface by unnecessary concealment, you actively taught people to slow themselves down and use the mouse. Because now they won’t ask about the underlines and now they won’t ask how the underlines make their work faster. And they won’t be faster workers. They never are. This is just a microcosm of a bigger problem though.

        I remember when Office/Start had “intelligent concealing menus” and the whole universe hated them, but Microsoft ignored the whole universe and invented the stupid modal Ribbon control which conceals entire pages of commands. I love those completely random brain farts mid-task. The Ribbon makes desktop as unproductive as mobile. It’s despicable. I can out-code anyone who says the Ribbon is awesome.

        1. xcomcmdr says:

          The Ribbon is awesome.

          I never got used to the bloated menus and toolbars of old Office (for example : Office XP).

          The ribbon made my productivity way higher when I have to use Word/Excel/etc… (which I still hate, but at least it has become tolerable)

          1. Ian Yates says:

            Agree – I’m a keyboard shortcut person when I can be, and I find the ribbon to be wonderful. Even things like Alt+I (for Insert) and then K (for bookmark) work well and you get little tooltips appearing in the ribbon during the sequence.

            Even the way the ribbon activates things like 2x table ribbon tabs when you’re in a table, and then if, in that table, you’ve also got a textbox, there’s a textbox tab, makes the whole process of interacting with some nested objects so much more straightforward.

            I don’t like how people have shoehorned the ribbon into apps that really don’t need one. But that’s not the fault of the ribbon, it’s apps trying to look modern. Unfortunately that just rapidly look dated. Having said that, I really miss the days where MS would come out with a UI paradigm and everyone would just follow it. That’s definitely not the case these days – can you imagine if the ribbon was put into Office today that it’d still be cloned by everything? I can’t :(

        2. Voo says:

          This whole comment just screams “my applications are designed by computer nerds for computer nerds.”

      3. Joshua says:

        Fun fact: if you start a program requiring elevation from the command line while explorer isn’t running, the UAC box is on top without focus. /me reaches for the mouse

      4. ender9 says:

        The whole UWP shift in Windows 10 UI is making it far less keyboard accessible. Eg. when I want to connect to a computer with Remote Desktop, with a different username than last time, I could previously press the down arrow on keyboard and immediately enter new username and password (single keypress). On Windows 10 I instead have to tab twice (down arrow doesn’t do anything) and press Enter or Spacebar – or click “More options”, then tab at least twice again (at least because if I have my smartcard inserted, it’s entries are shown between the useless first entry and the “Use another account” option; this also means that when using mouse, it’s not possible to rely on muscle memory, because the wanted entry moves around, is often hidden behind a scrollbar, and to make the matters worse, the smartcard entries don’t appear immediately, but after a short delay) and press Enter/Spacebar again before I can start typing a different username.

        What could previously be achieved by a single button press, or a single mouse click (in a fixed position) now takes at least 6 button presses, or two mouse clicks with a variable movement between them.

        Speaking of smartcard dialog boxes, they often appear behind the application that initiated them.

        Login screen is also crippled – while you were once able to press Ctrl+Alt+Del and immediately start typing the password (even if the password entry box hasn’t appeared yet), you now have to wait until the password entry box appears, because any keypresses done before that are lost.

    2. Gee Law says:

      You don’t have to press Alt again to use the mnemonic. It works as if it were in Ribbon — if you always know the mnemonics, press Alt+mnemonic; otherwise, press and release Alt to see the mnemonics, and then press the needed one.

      1. Karlis says:

        Is there some way to use a single button press? I’m pretty certain there was a time when in dialog boxes you could just press the mnemonic key (“Y”) instead of “Alt-Y”. I feel like I’m missing something, but I’ve been unable to figure it out (just like I never imagined pressing Alt-Y)

        1. Gee Law says:

          There was and is a time. In typical Win32 dialogs (your Notepad closing unsaved file dialog) you can just press the mnemonic to invoke the action. For classical Win32 menus (your Notepad menu), you usually have to Alt+mnemonic or Alt, then mnemonic, where in the second case after you press Alt, the focus moves to the menu bar. However, in File Explorer merge conflict dialog, you cannot Alt then mnemonic, neither can you “mnemonic”, and you have to Alt+mnemonic. It seems to me that if the dialog box has no other actionable elements than buttons, the mnemonics can be invoked without Alt.

  4. Of course, if you have a decent keyboard you don’t have to press Shift+F10 — just press the menu key.

  5. Deanna says:

    I’d seen this randomly, but didn’t see a pattern.
    Depending on how it is invoked makes do much sense though!

Skip to main content