Search code examples
c#filterresizecontextmenugravity

Dynamically filter and resize context menu c# while keeping its gravity to bottom


I have a system tray context menu with 26 items and an additional ToolStripTextBox menu item. When the user enters text to the filter textbox it continuously filters the menu items as the user types and hides categories on the fly by setting the ToolStripMenuItem Visible property to false.

It's working!

The issue is that when it gets filtered, the height of the context menu gets shorter from the bottom towards the top. The origin point for the menu is the upper right corner, causing it to shrink upwards. Since it is a system tray related context menu, I expect it to shrink downwards (bottom gravity).

How to make this happen?


Solution

  • Still not sure if there is a "proper" built-in method to do this...

    In the mean-time, here's a hack that changes the Bounds() of the ContextMenuStrip whenever the size changes. It simply shifts the ContextMenuStrip down/up by however much the height changed. I've wired up the Opened() and SizeChanged() events of my ContextMenuStrip and store the last Bounds() in the "lastBounds" variable at class level:

        private Rectangle lastBounds;
    
        private void contextMenuStrip1_Opened(object sender, EventArgs e)
        {
            lastBounds = contextMenuStrip1.Bounds;
        }
    
        private void contextMenuStrip1_SizeChanged(object sender, EventArgs e)
        {
            Rectangle rc = contextMenuStrip1.Bounds;
            int diff = lastBounds.Height - rc.Height;
            if (diff > 0)
            {
                contextMenuStrip1.Bounds = new Rectangle(new Point(rc.X, rc.Y + diff), rc.Size);
                lastBounds = contextMenuStrip1.Bounds;
            }
            else
            {
                contextMenuStrip1.Bounds = new Rectangle(new Point(rc.X, rc.Y - diff), rc.Size);
                lastBounds = contextMenuStrip1.Bounds;
            }
        }