Invoke NotifyIcon’s Context Menu

You would normally handle the MouseClick event to detect the click and call the ContextMenuStrip.Show() method:

    private void notifyIcon1_MouseClick(object sender, MouseEventArgs e) {
        contextMenuStrip1.Show(Control.MousePosition);
    }

But that doesn’t actually work properly, the CMS won’t close when you click outside of it. Underlying issue is a Windows quirk (aka “bug”) that is described in this KB article.

Invoking this workaround in your own code is pretty painful, the pinvoke is unpleasant. The NotifyIcon class has this workaround in its ShowContextMenu() method, they just made it difficult to get to since it is a private method. Reflection can bypass that restriction. I discovered this hack 5 years ago and nobody reported a problem with it yet. Set the NFI’s ContextMenuStrip property and implement the MouseUp event like this:

using System.Reflection;
...
    private void notifyIcon1_MouseUp(object sender, MouseEventArgs e) {
      if (e.Button == MouseButtons.Left) {
        MethodInfo mi = typeof(NotifyIcon).GetMethod("ShowContextMenu", BindingFlags.Instance | BindingFlags.NonPublic);
        mi.Invoke(notifyIcon1, null);
      }
    }

Leave a Comment