I have a Main method that creates a message loop called SysTrayApp:
void Main()
{
Application.Run(new SysTrayApp());
}
My SysTrayApp class adds a ContextMenu to the System Tray icon, then starts another message loop called MouseHook. MouseHook is a class that pinvokes mouse events. (Modeled after this class.)
class SysTrayApp : Form
{
public SysTrayApp()
{
// Does some GUI work
// Then starts another message loop
Application.Run(new MouseHook());
}
}
_
class MouseHook : Form
{
public MouseHook()
{
// Does some hooking stuff
}
}
In SysTrayApp, Application.Exit() is called when the user selects the Exit option from the context menu. The problem is that I have to call Exit twice (or add another Application.Exit) for the application to end. This is expected, but
I feel like I am going about this the wrong way. Calling Application.Exit() twice just seems wrong to me, but I’m new to the C# world. Should SysTrayApp and MouseHook be combined into one big class? MouseHook doesn’t seem like it should be apart of Windows.Form either. Maybe MouseHook needs to be on a new thread? Any suggestions?
EDIT: Oops. MouseHook did not have a third Application.Run()
Solution
I guess I was over thinking this. Still exploring C#, like I said. But here is what works:
Application.Run(new SysTrayApp()); in Main() is all you need. To start MouseHook, just do a MouseHook hook = new MouseHook(); in SysTrayApp.
Thanks @JonSkeet for helping me understand this. You are a machine!
You’re calling
Application.Runin theMouseHookconstructor and then when that returns, you’re callingApplication.Runagain (in theSysTrayAppconstructor) – you’re then calling it a third time when theSysTrayAppconstructor completes. If you’re going to run three different message loops, you should expect to have to exit three times (I’m amazed you’re only having to callApplication.Exittwice).You shouldn’t be calling
Application.Runin either of your constructors – the idea of a constructor blocking until a message pump has finishes is nasty, IMO. If you really want multiple message loops, they should be on different threads – but I wouldn’t advise you to do that. You should be fine just callingApplication.Runin yourMainmethod.