views:

248

answers:

3

Hi everyone!

I'm new here and have a really mysterious problem to start off. I'm a software developer in the UK and have over 15 years of experience but have only been developing in .Net for 18 months. My NotifyIcon mouse events are not firing!

I am using C# to write an application that starts as a NotifyIcon ('main app icon') and displays a ContextMenu on mouse right-click. This works fine: ContextMenu, forms launching and mouse click events firing.

A tiny bit of background: the application is supposed to sense the insertion of a usb 'device' (it does), interrogate it and create another NotifyIcon ('device icon') to allow the user to interact with that device. The 'main app icon', mentioned in my previous paragraph, allows the user to interact with the database and to configure the software.

To encapsulate these device interaction functions, I have constructed a 'device class' that contains the device NotifyIcon, ContextMenu, forms, mouse click events etc which allow interaction with the device.

The Problem The problem starts when I instantiate my 'device class' from the ManagementEventWatcher EventArrived event. If I instantiate the 'device class' in my program Main then the events fire correctly when I click the notifyicon.

So, please, can someone help me?

Cheers, in advance

Matthew

A: 

IIRC, the event usage (rather than WaitForNextEvent) works async. I would be interested to know what thread the event is being raised on. I wonder if there is no message pump servicing messages for your icon.

Do you have a form anywhere? Or something else with a message loop? I would be tempted to call into the form (using Control.Invoke), and ask the form to show the icon - since then it should have an active message pump.


Sorry for the delay; reading your comments, it sounds like you've broadly got a workaround. The only gotcha is cross-threaded issues; ideally, you would ask the UI to make such a change on the UI thread; for example, if you have a Form kicking around (owning the icon) - add to your form class:

// not a property, as there is no need to add a complex x-thread "get"
public void SetIconVisible(bool isVisible) {
    if(this.InvokeRequired) {
        this.Invoke((MethodInvoker) delegate {
            myIcon.Visible = isVisible;
        });
    } else {
        myIcon.Visible = isVisible;
    }
}

This does a thread-switch (if needed) to the UI thread. Any use?

Marc Gravell
Hi MarkThanks for the quick reply!I'm a bit too new at this to be able to answer your questions or to understand the suggestion.Is there some way I can make the 'message pump' you speak of? I do have forms but they are only displayed in reponse to the ContextMenus I mentioned.Which event are you asking about in your second sentence?CheersM
Will respond later - work time...
Marc Gravell
thanks Mark. My research is telling me that I need to do some cross-threading - which I only just understand. Something about delegates and invoking? hth
Mark, just to let you know - I worked out that I could create the class instances that have the NotifyIcon as members in the main thread and then make the NotifyIcon(s) visible when the USB device(s) are connected. It needed a bit of adjustment though because the NotifyIcon is created when it's first made visible, so I had to make sure that I set Visible to true then to false for each. The ManagementEventWatcher thread could then set the Visible property to true when the device gets connected. A workaround.
I be really interested in knowing how to instantiate the class in the main thread (so the events fire) but kick that off from the ManagementEventWatcher thread, if you had time to help?
A: 

Mark, just to let you know -

I worked out that I could create the class instances that have the NotifyIcon as members in the main thread and then make the NotifyIcon(s) visible when the USB device(s) are connected.

It needed a bit of adjustment though because the NotifyIcon is created when it's first made visible, so I had to make sure that (in the main thread) I set Visible to true then to false for each - giving rise to the need for limiting the number of instances.

The ManagementEventWatcher thread could then set the Visible property to true when the device gets connected.

A workaround.

(see replies to your comments)

added some thoughts - I hope it helps.
Marc Gravell
A: 

So the answer is:

The events will only work if when you make the NotifyIcon visible, you do it in the main thread. So the code given by Marc Gravell is the solution.

Jonas