views:

2966

answers:

7

What's the correct way to write a Windows system tray application in C#?

Not an application that can minimize to the tray, but one that only exists in the tray, and can have an icon tool tip and "right click" menu.

+4  A: 

As far as I'm aware you have to still write the application using a form, but have no controls on the form and never set it visible. Use the NotifyIcon (an MSDN sample of which can be found here) to write your application.

Matthew Steeples
Not quite. Your form(s) can contain controls, but it should be hidden by default.
Rune Grimstad
You do not need any form. After a new Window App creation wizard, just delete the Form1 and remove the code opening it.You can write it all from Program.cs with NotifyIcon and ContextMenu on it. Nothing more required.
Wolf5
I know it can contain controls, but OP doesn't want it to
Matthew Steeples
+4  A: 

"System tray" application is just a regular win forms application, only difference is that it creates a icon in windows system tray area. In order to create sys.tray icon use NotifyIcon component , you can find it in Toolbox(Common controls), and modify it's properties: Icon, tool tip. Also it enables you to handle mouse click and double click messages.

And One more thing , in order to achieve look and feels or standard tray app. add followinf lines on your main form show event:

private void MainForm_Shown(object sender, EventArgs e)
{
    WindowState = FormWindowState.Minimized;
    Hide();
}
Gordon Freeman
+3  A: 

As mat1t says - you need to add a NotifyIcon to your application and then use something like the following code to set the tooltip and context menu:

this.notifyIcon.Text = "This is the tooltip";
this.notifyIcon.ContextMenu = new ContextMenu();
this.notifyIcon.ContextMenu.MenuItems.Add(new MenuItem("Option 1", new EventHandler(handler_method)));

This code shows the icon in the system tray only:

this.notifyIcon.Visible = true;  // Shows the notify icon in the system tray

The following will be needed if you have a form (for whatever reason):

this.ShowInTaskbar = false;  // Removes the application from the taskbar
Hide();

The right click to get the context menu is handled automatically, but if you want to do some action on a left click you'll need to add a Click handler:

    private void notifyIcon_Click(object sender, EventArgs e)
    {
        var eventArgs = e as MouseEventArgs;
        switch (eventArgs.Button)
        {
            // Left click to reactivate
            case MouseButtons.Left:
                // Do your stuff
                break;
        }
    }
ChrisF
You do not need the ShowInTaskbar = false if you do not add a default Form to show.
Wolf5
True - I'll update the answer. I had originally assumed there would be a form
ChrisF
+6  A: 

I've wrote a traybar app with .NET 1.1 and I didn't need a form.
First of all, set the startup object of the project as a Sub Main, defined in a module.
Then create programmatically the components: the NotifyIcon and ContextMenu.
Be sure to include a MenuItem "Quit" or similar
Bind the ContextMenu to the NotifyIcon.
Invoke Application.Run()
In the event handler for the Quit MenuItem be sure to call set NotifyIcon.Visible = False, then Application.Exit().
Add what you need to the ContextMenu and handle properly :)

Turro
+4  A: 
  1. Create a new Windows Application with the wizard.
  2. Delete Form1 from the code.
  3. Remove the code in Program.cs starting up the Form1.
  4. Use the NotifyIcon class to create your system tray icon (assign an icon to it).
  5. Add a contextmenu to it.
  6. Or react to NotifyIcon's mouseclick and differenciate between Right and Left click, setting your contextmenu and showing it for which ever button (right/left) was pressed.
  7. Application.Run() to keep the app running with Application.Exit() to quit. Or a while(bRunning){Application.DoEvents;Thread.Sleep(10);}. Then set bRunning = false to exit the app.
Wolf5
The program stops executing when you reach the end of Main and has no UI thread. How do you take care of this is your solution? If you've solved those problems then you get my vote :)
Matthew Steeples
You get my vote. Maybe just mention that you still need to call Application.Run without any params?
Kevin Thiart
Updated with an alternative to App.Run.
Wolf5
A: 

The answers given here are great, but I wanted to share a resource. There is a tutorial for exactly this over on Experts Exchange.

Brad