BUG: ContextMenu Shortcut (Accelerator) Problem

I've only verified this with .NET 1.0.x, so if it's been fixed in 1.1.x please let me know and I'll quietly go away.

It appears shortcuts (accelerators) are not handled properly for top-level menu items in a ContextMenu.  The problem occurs in this manner:

1) Bring up a context menu (by right-clicking, etc.).
2) Assume some top-level menu item (call it MyCommand) is disabled while a delegate is handling the Popup event of ContextMenu based on the state of the application.
3) Context menu is displayed.
4) Context menu is closed.
5) State of the application changes such that MyCommand should be enabled.
6) Press the shortcut key for MyCommand.

In this case, nothing happens because the menu item is still disabled.  This, in turn, is because the Popup event of the containing ContextMenu is never raised (look at System.Windows.Forms.Menu.ProcessCmdKey and System.Windows.Forms.MenuItem.ShortcutClick in IL DASM), therefore the application never gets a chance to re-enable the menu item.

This only affects top-level menu items because the code in System.Windows.Forms.MenuItem.ShortcutClick only checks to see if the menu item is a child of another menu item.  Since top-level items are either a child of a MainMenu or a ContextMenu, the top-level menu items never get a chance to update their state.  I suppose a simple hack would be to test the menu item container to see if it is either a MenuItem OR a ContextMenu.  One could also override Menu.ProcessCmdKey in ContextMenu and force a Popup event if the associated menu item is a descendant.

Even though this behavior occurs for top-level non-popup menu items in a MainMenu, I don't really consider it a bug for two reasons.  1) The Windows Usability Group would probably have a cow if they saw command menu items at the top level of a main menu, and 2) since MainMenus are normally always visible, the proper solution to update the top-level menu item state is to do it in the idle loop (similar to how toolbar buttons would be handled).

Any verification and/or comments would be appreciated.

Steve


Answer this question

BUG: ContextMenu Shortcut (Accelerator) Problem

  • wabroussard

    I have encountered something similar regarding the Shortcut Key property on MainMenu items...  If the MenuItem is disabled, the ShortcutKey still executes.  I ultimately had to resort to programmatically toggling the presence of the Shortcut based on app state.
  • Julien Ellie

    You are correct, ContextMenu.Popup is raised before the context menu is about to be displayed.  However, it is *NOT* called (in 1.0.3705 at least) as part of shortcut key processing (see the code for MenuItem.ShortcutClick).  Since my original post, I was able to diff the code for MenuItem.ShortcutClick between 1.0.3705 and 1.1.4322, and the only change made was to the method signature (the addition of the "strict" attribute).

    My best guess is that the designers assumed top-level menu items would never be associated with shortcut keys (which is a good assumption).  Enter the unfortunate side effect that context menu items are top-level, and your shortcut key processing is broken for those items (when they can be potentially disabled).

    Steve

  • SergStone

    I am not sure if I entirely understand what you are asking.

    The MenuItem Popup event is raised when a top-level item is about to display its subitems.  If you want a Popup event to be raised before the top-level items are shown, use the ContextMenu's Popup event.  I have tried this on 1.1.4322 and the ContextMenu's Popup event is raised as expected.  

    Hope this helps,

    Andrea


  • BUG: ContextMenu Shortcut (Accelerator) Problem