Auto-hide menu in Windows Forms

Some times you need to make the menu of the form auto hide to provide more space for other controls on the form. To show and hide the menu, it’s enough to set its Visible property. But to make it auto-hide you should handle a couple of other events:

Show or hide using mouse

To show or hide it based on mouse position, you can use a timer and in the time check if the mouse is close to the top edge of the form, then show the menu.

To hide it, you can check if the mouse is not in the client area of the menu, and there is no menu item activated or open, then you can hide it. In the example, I used two different timers for show and hide to be able to set different delay for show and hide:

Auto-hide menu mouse activation

Show or hide using ALT key

To activate it by Alt key, 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:

Auto-hide menu keyboard activation

Code

Drop a MenuStrip control on the form and add some menu items to it. For test, you can right click on it and click on Insert standard items to add standard menu items. Then attach event handlers to the events:

bool menuIsActive = false;
private void Form1_Load(object sender, EventArgs e)
{
    MessageBox.Show("Menu is auto-hide. Hover the mouse under the titlebar to see the menu.");
    this.menuStrip1.Visible = false;
}

private void hideTimer_Tick(object sender, EventArgs e)
{
    var p = this.menuStrip1.PointToClient(MousePosition);
    if (menuIsActive)
        return;
    if (menuStrip1.ClientRectangle.Contains(p))
        return;
    foreach (ToolStripMenuItem item in menuStrip1.Items)
        if (item.DropDown.Visible)
            return;
    this.menuStrip1.Visible = false;
}

private void showTimer_Tick(object sender, EventArgs e)
{
    var p = this.PointToClient(MousePosition);
    if (this.ClientRectangle.Contains(p) && p.Y < 10)
        this.menuStrip1.Visible = true;
}
private void menuStrip1_MenuActivate(object sender, EventArgs e)
{
    menuIsActive = true;
}
private void menuStrip1_MenuDeactivate(object sender, EventArgs e)
{
    menuIsActive = false;
    this.BeginInvoke(new Action(() => { this.menuStrip1.Visible = false; }));
}
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);
}

Download

You can download the full working example:

You May Also Like

About the Author: Reza Aghaei

I’ve been a .NET developer since 2004. During these years, as a developer, technical lead and architect, I’ve helped organizations and development teams in design and development of different kind of applications including LOB applications, Web and Windows application frameworks and RAD tools. As a teacher and mentor, I’ve trained tens of developers in C#, ASP.NET MVC and Windows Forms. As an interviewer I’ve helped organizations to assess and hire tens of qualified developers. I really enjoy learning new things, problem solving, knowledge sharing and helping other developers. I'm usually active in .NET related tags in stackoverflow to answer community questions. I also share technical blog posts in my blog as well as sharing sample codes in GitHub.

Leave a Reply

Your email address will not be published. Required fields are marked *