Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How would one attach a ContextMenuStrip to a NotifyIcon

I'm trying to make a NotifyIcon display a context menu, even if it's clicked with the left mouse button. I can get it to display in the correct location with this in the icon's MouseDown event:

sysTrayIcon.ContextMenuStrip = TrayContextMenu
If e.Button = MouseButtons.Left Then TrayContextMenu.Show()

But because sysTrayIcon isn't specified as the control when I left click, it doesn't clear from the screen if I click outside the menu or press escape.

I know the usual method is to use the menu's overloaded Show(control, location) method, but that's raising this error:

Value of type 'System.Windows.Forms.NotifyIcon' cannot be converted to 'System.Windows.Forms.Control'.

So how can I attach the menu to the notify icon, please?

like image 784
Ants1060 Avatar asked Mar 22 '23 00:03

Ants1060


1 Answers

Yes, this code cannot work correctly as posted. Several secret incantations are required to get the context menu at the correct location and for mouse capture to be setup correctly so that clicking outside of it works properly. These incantations are required because it is Windows Explorer that manages the notification icon, not your program.

You need to leave it up to the NotifyIcon class to get this right. A significant hang-up however is that it doesn't expose the method that displays the context menu, it is a private method. Only thing you can do about that is to use Reflection to invoke the method. Like this (using the default names):

Imports System.Reflection
...
    Private Sub NotifyIcon1_MouseDown(sender As Object, e As MouseEventArgs) Handles NotifyIcon1.MouseDown
        NotifyIcon1.ContextMenuStrip = ContextMenuStrip1
        Dim mi = GetType(NotifyIcon).GetMethod("ShowContextMenu", BindingFlags.NonPublic Or BindingFlags.Instance)
        mi.Invoke(NotifyIcon1, Nothing)
    End Sub
like image 65
Hans Passant Avatar answered Mar 23 '23 14:03

Hans Passant