10

I mean when the user starts my application(exe). I want it to start directly in system tray, without showing the window. Like antivirus softwares & download managers, which start and run in the system tray silently.

I want the same effect and when user click the "show" button of the notifyIcon's contextmenustrip then only application should show GUI.

I'm using this, but its not working

    private void Form_Load(object sender, EventArgs e)
    {
        this.Hide();
    }

May be I need to have Main() function in some other class which has no GUI but has notifyIcon & ContextMenuStrip whose option will instantiate the GUI window class. Right?

Jhonny D. Cano -Leftware-
  • 17,663
  • 14
  • 81
  • 103
claws
  • 52,236
  • 58
  • 146
  • 195
  • See also this question - http://stackoverflow.com/questions/807005/c-net-winforms-instantiate-a-form-without-showing-it – ChrisF Oct 24 '09 at 12:57
  • Sorry to dredge up an old topic. I got everything except one major thing. I understand that `Application.Run()` essentially relinquishes control (?). What I want to do is have code doing something with no user interaction (say it's processing data and writing it to a file). Where would I put this code so that it's executing while the program is sitting in the system tray? – Barry Dysert Oct 22 '13 at 15:57
  • @BarryDysert: `Application.Run()` starts up the windows message pump. If you don't have this call somewhere then your tray icon won't work at all. Without knowing anything about what you're actually trying to achieve, I'd say to look at threads, just be aware of issues modifying UI stuff on threads other than the one that `Application.Run()` was called from. – Matthew Scharley Dec 12 '13 at 22:38

3 Answers3

31

The way I usually setup something like this is to modify the Program.cs to look something like the following:

    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        using (NotifyIcon icon = new NotifyIcon())
        {
            icon.Icon = System.Drawing.Icon.ExtractAssociatedIcon(Application.ExecutablePath);
            icon.ContextMenu = new ContextMenu(new MenuItem[] {
                new MenuItem("Show form", (s, e) => {new Form1().Show();}),
                new MenuItem("Exit", (s, e) => { Application.Exit(); }),
            });
            icon.Visible = true;

            Application.Run();
            icon.Visible = false;
        }
    }

Using this, you don't need to worry about hiding instead of closing forms and all the rest of the hacks that can lead to... You can make a singleton form too instead of instantiating a new Form every time you click the show form option. This is something to build off of, not the end solution.

Matthew Scharley
  • 127,823
  • 52
  • 194
  • 222
  • 1
    As a further note, you need to be using a GUI project, despite this code appearing before any GUI pops up, otherwise you'll get a console window popping up, which is even worse than the original problem! – Matthew Scharley Oct 24 '09 at 12:15
  • Awesome!! This is exactly what I'm looking for. But how do I change the icon.Icon ? I want to put my own *.ico here. instead of extracted one. – claws Oct 24 '09 at 13:06
  • 1
    `new System.Drawing.Icon("C:\Path\To\Icon.ico")` from memory, or use a resource (recommended). See this other question for details on how to create/use resources: http://stackoverflow.com/questions/90697/how-to-create-and-use-resources-in-c-net-vs-2008 – Matthew Scharley Oct 24 '09 at 13:18
  • 1
    Wow... I've been programming in C# for almost 10 years, and it's the first time I see a solution to that problem that isn't a dirty hack. Well done ;) – Thomas Levesque Mar 25 '11 at 09:12
  • How would you define the default context menu item (e.g. to open form on simple icon click) ? – Bitterblue Nov 18 '13 at 14:46
  • @mini-me: It's late, but I believe all types of clicks (left, double, ..) are all handled via events on the NotifyIcon. Simply hook the relevant event and open your form that way. – Matthew Scharley Dec 12 '13 at 22:32
  • Actually I wanted "Show form" to be bold. Like my AntiVirus is showing me a bold item, that I also access with a double click on the icon. It's probably a different question about context menus etc. – Bitterblue Dec 13 '13 at 08:50
  • @mini-me: It's been a while since I looked at C#, but I *believe* that either the ContextMenu or the MenuItem's have a default property to make them display bold like that. Wiring up the default action though is still up to you though, *I think*. YMMV. – Matthew Scharley Dec 16 '13 at 22:47
  • There seems to be a problem with this solution: I am using a MSI installer in my project, when uninstalling the application should automatically be closed. But when the form was never visible (the ApplicationContext's MainForm property is not set), WM_CLOSE events can't be handled. – ndreisg Feb 12 '19 at 09:59
  • @ndreisg I don't have any practical answers since I haven't done Windows development much in the 10 years since this answer was put forth. More accurately though, there's no window to receive WM_ events at all. Rather, your installer needs to send a different/better message to the application. In Unix land, the obvious solution here would be a process signal. I'm not sure what the analogue is in Windows land. Perhaps a named pipe or similar. – Matthew Scharley Feb 14 '19 at 08:31
  • I think I don't really have control over how Windows Installer is closing the process. I solved this by setting the `MainForm` again and hiding it on the forms `Load` event. Exactly like the code example in the question does but before hiding i set `ShowInTaskbar = false;` – ndreisg Feb 14 '19 at 14:58
3

You need to set up the notify icon as well.

Either manually or via the toolbar (drag a notifyIcon onto your form) create the notifyIcon:

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

Then add this code to Form_Load():

// Notify icon set up
notifyIcon.Visible = true;
notifyIcon.Text = "Tooltip message here";
this.ShowInTaskbar = false;
this.Hide();

Though this will, as has been pointed out, briefly show the form before hiding it.

From the accepted answer of this question, the solution appears to be to change:

Application.Run(new Form1());

to:

Form1 f = new Form1();
Application.Run();        

in Main().

Community
  • 1
  • 1
ChrisF
  • 134,786
  • 31
  • 255
  • 325
  • Actually I've the notifyIcon setup. So, I just added the this.ShowInTaskbar = false; but the problem is that window is showing for an instant and then hiding. I don't want this. – claws Oct 24 '09 at 12:08
  • Check out my solution then claws. This will fix this issue. – Matthew Scharley Oct 24 '09 at 12:10
  • @ChrisF: hacks on hacks... that'll still pop up a window, it's just that it'll start minimised and will be less likely to be noticed. – Matthew Scharley Oct 24 '09 at 12:16
0

Have you created a Windows Application in C#? You need to drag a NotifyIcon control onto the form, the control will be placed below the form because it has no visual representation on the form itself.

Then you set its properties such as the Icon...

Try this one first...

Julius A
  • 38,062
  • 26
  • 74
  • 96