Home > Software design >  .NET6 NotifyIcon ContextMenu wont show
.NET6 NotifyIcon ContextMenu wont show

Time:01-28

So I have built an app in .NET 6, and I'm able to get it to show the NotifyIcon in the Tray Area but the context menu (right-click) on the NotifyIcon just will not show up.

I built this code following Implement a menu on tray icon for .NET 5/6 win forms (and then changing it so it was not using inline creation to see if it was causing this issue)

So the only thing i can think is that my Application does not have a Form so I'm running this code from the Program.cs file.

internal class Program
{
    private static NotifyIcon notifyIcon;
    private static ContextMenuStrip cms;

    private static async Task Main(string[] args)
    {
        notifyIcon = new NotifyIcon();
        notifyIcon.Icon = new Icon("Assets/icon.ico");
        notifyIcon.Text = "Notify";

        cms = new ContextMenuStrip();

        cms.Items.Add(new ToolStripMenuItem("Reconnect", null, new EventHandler(Reconnect_Click)));
        cms.Items.Add(new ToolStripSeparator());
        cms.Items.Add(new ToolStripMenuItem("Quit", null, new EventHandler(Quit_Click), "Quit"));

        notifyIcon.ContextMenuStrip = cms;
        notifyIcon.Visible = true;

        new Thread(() =>
        {
            while (true)
            {
                Thread.Sleep(10000);
                // do application background task
            }
        }).Start();
    }

    protected static void Reconnect_Click(object? sender, System.EventArgs e)
    {
        // do something
    }

    protected static void Quit_Click(object? sender, System.EventArgs e)
    {
        Environment.Exit(0);
    }
}

Updated the ContextMenuStrip instance to be saved against the class not built in the Main Context/Scope

CodePudding user response:

You need to have a message loop that handles Windows messages that are used in Windows applications to communicate between the operating system and the user interface of your application.

If you want an application without having a visible form but still run a message loop, use the Application.Run method with an ApplicationContext object. You do then also use the context to signal the end of the application.

Sample code:

internal static class Program
{
    private static NotifyIcon notifyIcon;
    private static ContextMenuStrip cms;
    private static ApplicationContext context;

    [STAThread]
    static void Main()
    {
        ApplicationConfiguration.Initialize();

        notifyIcon = new NotifyIcon();
        notifyIcon.Icon = new Icon("Assets/icon.ico");
        notifyIcon.Text = "Notify";

        cms = new ContextMenuStrip();

        cms.Items.Add(new ToolStripMenuItem("Reconnect", null, new EventHandler(Reconnect_Click)));
        cms.Items.Add(new ToolStripSeparator());
        cms.Items.Add(new ToolStripMenuItem("Quit", null, new EventHandler(Quit_Click), "Quit"));

        notifyIcon.ContextMenuStrip = cms;
        notifyIcon.Visible = true;

        // Create an ApplicationContext and run a message loop
        // on the context.
        context = new ApplicationContext();
        Application.Run(context);

        // Hide notify icon on quit
        notifyIcon.Visible = false;
    }

    static void Reconnect_Click(object? sender, System.EventArgs e)
    {
        MessageBox.Show("Hello World!");
    }

    static void Quit_Click(object? sender, System.EventArgs e)
    {
        // End application though ApplicationContext
        context.ExitThread();
    }
}
  • Related