Search code examples
c#winforms.net-6.0menustrip

Event when a menu item is highlighted


Has anyone figured out an event that fires whenever a menu item is highlighted?

I would like to display a description of each menu command in the status bar as they are highlighted. I'd like this to happen whether they are highlighted using the mouse or the keyboard.

But after considerable effort, I don't see any event like this. I even tried overriding WndProc to detect raw menu messages but found none are sent. Apparently, WinForms doesn't use the standard Windows menus.

It seems like knowing when a menu item is clicks and when it is selected (highlighted without being clicked) should be the two most important menu events. I don't know why the latter wouldn't be supported.

Anyone been able to figure this out?

UPDATE

With the help of answers given here, I was able to come up with a complete solution. I have posted that solution as open source on NuGet and GitHub.


Solution

  • In addition to the mouse events, you can add the keyboard keys part by handling the KeyUp event of the owner menu to get the selected item and display a description in a status-bar label.

    public YourForm()
    {
        InitializeComponent();
    
        menuStrip1.ShowItemToolTips = false;
        menuStrip1.KeyUp += OnToolStripKeyUp;
    
        foreach (var item in GetAllToolStripItems(menuStrip1.Items))
        {
            item.AutoToolTip = false;
            item.MouseEnter += OnToolStripItemMouseEnter;
            item.MouseLeave += OnToolStripItemMouseLeave;
    
            if (item.GetCurrentParent() is ToolStrip dm)
            {
                dm.ShowItemToolTips = false;
                dm.KeyUp -= OnToolStripKeyUp;
                dm.KeyUp += OnToolStripKeyUp;
            }
        }
    }
    
    private void OnToolStripItemMouseEnter(object sender, EventArgs e)
    {
        sbrLabel.Text = (sender as ToolStripItem).ToolTipText;
    }
    
    private void OnToolStripItemMouseLeave(object sender, EventArgs e)
    {
        sbrLabel.Text = "Ready";
    }
    
    private void OnToolStripKeyUp(object sender, KeyEventArgs e)
    {
        var s = sender as ToolStrip;
        var selItem = s.Items.OfType<ToolStripMenuItem>().FirstOrDefault(x => x.Selected);
    
        sbrLabel.Text = selItem?.ToolTipText;
    }
    
    private IEnumerable<ToolStripItem> GetAllToolStripItems(ToolStripItemCollection tsic)
    {
        foreach (var tsi in tsic.Cast<ToolStripItem>())
        {
            yield return tsi;
    
            if (tsi is ToolStripDropDownItem tsddi && tsddi.HasDropDown)
                foreach (var ddi in GetAllToolStripItems(tsddi.DropDownItems))
                    yield return ddi;
        }
    }
    

    SO70731362