Search code examples
c#.netwinformsmenustrip

Autohide MenuStrip - How to activate it when showing?


I have a MenuStrip and I make it AutoHide using following code. It hides/shows prefect but when a control get focus, by pressing Alt key, MenuStrip shows but it is not active and there is not small underline under shortcut keys for example under 'F' for File , and pressing 'F' will not open it). How can I correctly active it?

Note: I used MenuDeactivate instead of it but it did not work prefect.

bool menuBarIsHide = true;
bool altKeyIsDown = false;
bool alwaysShowMenuBar=false;
//KeyPreview is true;
//for prevent glitch(open/close rapidly)
void Form1_KeyUp(object sender, KeyEventArgs e)
{
    if ((Control.ModifierKeys & Keys.Alt) != 0)
        altKeyIsDown = false;
}
void Form1_KeyDown(object sender, KeyEventArgs e)
{
    if ((Control.ModifierKeys & Keys.Alt) != 0)
    {
        if (altKeyIsDown)
            return;
        if (!alwaysShowMenuBar)
        {
            if (menuBarIsHide)
            {
                menuBar.Show();
                menuBarIsHide = false;
                //manage container height
            }
            else
            {
                menuBar.Hide();
                menuBarIsHide = true;
                //manage container height
            }
        }
    }
}

Solution

  • You can override ProcessCmdKey to handle Alt key to toggle the menu visibility. Also to activate menu, call internal OnMenuKey method of MenuStrip. Also handle MenuDeactivate to make the menu invisible after finishing your work with menu, but you need to make the menu invisible using BeginInvoke.

    protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
    {
        if (keyData == (Keys.Alt | Keys.Menu))
        {
            if (!this.menuStrip1.Visible)
            {
                this.menuStrip1.Visible = true;
                var OnMenuKey = menuStrip1.GetType().GetMethod("OnMenuKey", 
                    System.Reflection.BindingFlags.NonPublic | 
                    System.Reflection.BindingFlags.Instance);
                OnMenuKey.Invoke(this.menuStrip1, null);
            }
            else
            {
                this.menuStrip1.Visible = false;
            }
            return true;
        }
        return base.ProcessCmdKey(ref msg, keyData);
    }
    private void menuStrip1_MenuDeactivate(object sender, EventArgs e)
    {
        this.BeginInvoke(new Action(() => { this.menuStrip1.Visible = false; }));
    }