Search code examples
c#wpfwcfnotifyiconcontextmenustrip

notifyicon not raising click event and contextmenustrip not showing


I have a problem where the notifyicon is showing up fine, and displaying its bubble, but it does not raise its click event when clicked.

It should show its contextmenustrip, but if i add contextmenustrip.show(); into the code, it just shows the shadows of the menu but not the menu itself.

the function is part of a WPF application and is called via a named pipe from a WCF service application.


Code, in case you need it:

in the service app:

public partial class Service1 : ServiceBase
    {
        ChannelFactory<ILicenseWatchingServiceUIHost> pipeFactory;
        ILicenseWatchingServiceUIHost LWSProxy;


        public Service1()
        {
            InitializeComponent();    
        }

        #region service states

        protected override void OnStart(string[] args)
        {
            pipeFactory = new ChannelFactory<ILicenseWatchingServiceUIHost>(
                new NetNamedPipeBinding(),
                new EndpointAddress("net.pipe://localhost/LWSPipe"));
            LWSProxy = pipeFactory.CreateChannel();
            Run();
        }

        //...

        private void Run()
        {
            //...

            LWSProxy.Execute();
        }
    }

server creation in WPF app:

public partial class App : Application
    {
        ServiceHost host = new ServiceHost(typeof(LicenseWatchingServiceUserInterface), new Uri[] { new Uri("net.pipe://localhost") });

        public App()
        {
            StartServer();
        }

        private void StartServer()
        {
            host.AddServiceEndpoint(typeof(ILicenseWatchingServiceUIHost), new NetNamedPipeBinding(), "LWSPipe");
            host.Open();

            BackgroundWorker worker = new BackgroundWorker();
            System.Windows.Threading.Dispatcher dispatcher = this.Dispatcher;
        }
    }

and finally:

public class LicenseWatchingServiceUserInterface : ILicenseWatchingServiceUIHost
    {
        private System.ComponentModel.IContainer components = null;
        private System.Windows.Forms.NotifyIcon notifyIcon;
        private System.Windows.Forms.ContextMenuStrip contextMenuStrip;

        void Execute(){
        //...
        contextmenustrip.show(); //does not work
        }

        //does not get raised
        private void notifyIcon_Click(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                    contextMenuStrip.Show(Cursor.Position.X, Cursor.Position.Y);
                }
                else if (e.Button == MouseButtons.Left)
                {
                    Execute();
                }
            }
        }

        void Init()
        {
            this.components = new System.ComponentModel.Container();
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(LicenseWatchingServiceUserInterface));

            this.notifyIcon = new System.Windows.Forms.NotifyIcon();
            this.contextMenuStrip = new System.Windows.Forms.ContextMenuStrip();

            // 
            // notifyIcon
            // 
            this.notifyIcon.BalloonTipIcon = System.Windows.Forms.ToolTipIcon.Info;
            this.notifyIcon.ContextMenuStrip = this.contextMenuStrip;
            this.notifyIcon.Icon = iconLoading;
            this.notifyIcon.Visible = true;
            //clickhandler is in fact wired up
            this.notifyIcon.MouseClick += new System.Windows.Forms.MouseEventHandler(this.notifyIcon_Click);
            // 
            // contextMenuStrip
            // 
            this.contextMenuStrip.ImageScalingSize = new System.Drawing.Size(20, 20);
            this.contextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.settingsToolStripMenuItem,
            this.openLicenseManagerToolStripMenuItem,
            this.closeToolStripMenuItem});
            this.contextMenuStrip.Name = "contextMenuStrip";
            this.contextMenuStrip.Size = new System.Drawing.Size(234, 128);
            //
            // contextmenustrip items...
            //
        }
        //...
    }

Solution

  • Figured it out:

    The LWSProxy.Execute(); was creating an instance of the LicenseWatchingServiceUserInterface class in a background thread, wich was causing problems. The notifyicon has to be created in the main thread, otherwise the eventhandlers won't work. My solution is a helper class (just put it below the class App) :

    public class LicenseWatchingServiceUICreator : ILicenseWatchingServiceUIHost
        {
    
            public void Execute(List<LicenseInfoContainerExpiring> elcs, List<LicenseInfoContainerUntrusted> ulcs)
            {
                System.Windows.Application.Current.Dispatcher.Invoke(new Action(() => 
                {
                    LicenseWatchingServiceUserInterface LWSUI = new LicenseWatchingServiceUserInterface(elcs, ulcs); 
                }));
            }
    
        }
    

    with minor tweaking, this classes execute method will get called through the pipe, and it will create an instance of my class in the main thread. Now my UI works as usual.