2

My WPF application shows a window and when the user clicks a button, it begins to run its tasks and minimizes to a tray item in the notification area with a context menu where I would like the user to be able to cancel the operation.

The context menu worked before using a BackgroundWorker, however, cancellation did not. Since I've implemented a background worker,the context menu does not appear once the .runworkerasync() method has run.

My Notify Icon:

public NotifyIcon myNotifyIcon;

When my application runs I set it up like this:

private void setup_NotifyIcon()
{
    myNotifyIcon = new NotifyIcon();
    setTrayIcon();

    myNotifyIcon.MouseDown += new MouseEventHandler(myNotifyIcon_MouseDown);

    var menuItemCancel = new MenuItem("Cancel Parsing");
    var contextMenu = new ContextMenu();
    menuItemCancel.Click += new System.EventHandler(this.menuItemCancel_Click);

    contextMenu.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { menuItemCancel });
    myNotifyIcon.ContextMenu = contextMenu;

}

    private void menuItemCancel_Click(object Sender, EventArgs e)
    {
        //do something
    }

    void myNotifyIcon_MouseDown(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Right)
        {
            //do something
        }
    }

Then when the user clicks the button:

worker.RunWorkerAsync();

Why won't myNotifyIcon.MouseDown += new MouseEventHandler(myNotifyIcon_MouseDown); trigger the context menu?

user
  • 1,261
  • 2
  • 21
  • 43
  • Maybe you dont show your context menu in the UI thread context?! See here pls https://stackoverflow.com/questions/11625208/accessing-ui-main-thread-safely-in-wpf – Sebastian Richter Aug 15 '17 at 21:12
  • 1
    The snippets are pretty useless to diagnose this problem. Don't minimize your UI. Is it still responsive? Can you, say, still close the window? If it is not then it also is not going to respond to the MouseDown event. – Hans Passant Aug 15 '17 at 22:21
  • As a side note the `BackgroundWorker` class is [technologically obsolete](https://stackoverflow.com/questions/12414601/async-await-vs-backgroundworker/64620920#64620920). You shouldn't really use this thing for new development. Use `Task.Run` and async/await instead. – Theodor Zoulias May 20 '21 at 10:43

2 Answers2

4

The solution turned out to be a threading issue as suggested by Sebastian in the comments.

The key was to start the icon on another thread using Application.Run() and to make the icon visible within that code.

Once this was done, right-clicking on the icon worked, as did the cancellation functionality being handled.

    private void setup_NotifyIcon()
    {
        Thread notifyThread = new Thread(
        delegate ()
        {
            myNotifyIcon = new NotifyIcon();
            setTrayIcon();

            myNotifyIcon.MouseDown += new MouseEventHandler(myNotifyIcon_MouseDown);

            mnuCancel = new MenuItem("Cancel Parsing");
            menu = new ContextMenu();
            mnuCancel.Click += new System.EventHandler(menuItemCancel_Click);

            menu.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { mnuCancel });
            myNotifyIcon.ContextMenu = menu;

            myNotifyIcon.BalloonTipIcon = System.Windows.Forms.ToolTipIcon.Info; //Shows the info icon so the user doesn't thing there is an error.
            myNotifyIcon.BalloonTipText = "The P6 Parser will minimize to the system tray while working.";
            myNotifyIcon.BalloonTipTitle = "Processing...";

            myNotifyIcon.Visible = true;
            myNotifyIcon.ShowBalloonTip(500);

            myNotifyIcon.Visible = true;
            System.Windows.Forms.Application.Run();
        });
        notifyThread.Start();

    }
user
  • 1,261
  • 2
  • 21
  • 43
-2

in Program.cs change the Attribute [STAThread] to [MTAThread]