HOWTO · Csharp
How to Minimize Applications in the System Tray in C#
This article explains how to minimize a Windows Forms application to the system tray with NotifyIcon in C#, hiding the form and restoring it from the tray icon.
On this page
This article explains how to minimize a Windows Forms application to the system tray instead of the taskbar using C#, so the app keeps running in the background while staying reachable through a small tray icon.
Why minimize a Windows Forms app to the system tray
Windows Forms is the desktop GUI framework built into .NET. Its controls (buttons, menus, text fields, checkboxes, and so on) live in the System.Windows.Forms namespace, and a sign-up or login form is a typical example of what you can build with it. You can find more background on Windows Forms applications here.
By default, minimizing a Windows Forms app leaves its button on the taskbar. That is fine for applications you switch to frequently, but a program that only needs to run in the background wastes taskbar space, and the taskbar quickly becomes cluttered and hard to navigate.
The system tray — the notification area at the bottom-right corner of the taskbar — is the usual place for such applications. Each background app is represented by a small icon: out of sight, but still one click away. Chat clients and antivirus software commonly work this way, and a tray app can still notify the user with a balloon tip when something needs attention.
In short, NotifyIcon lets a Windows Forms app minimize to the system tray instead of the taskbar while it continues running. The rest of this article shows how to wire that behavior up.
Configure NotifyIcon
NotifyIcon is a component in the System.Windows.Forms namespace that draws and manages the icon your app shows in the system tray. It is not a visible control: when you drag it onto a form, it lands in the component tray below the designer rather than on the form’s surface.
In Visual Studio, open the Toolbox and double-click or drag NotifyIcon onto the form:
This adds a notifyIcon1 component to the form. The properties that matter for this tutorial are:
Icon: the icon shown in the system tray — the most important property. It takes aSystem.Drawing.Icon, and the Visual Studio designer’s picker accepts.icofiles directly. Other image formats must first be converted into anIconin code, so an.icofile remains the practical choice for the tray.Text: the tooltip shown when the cursor hovers over the tray icon.Visible: whether the icon appears in the tray. Keep itFalsewhile the form is visible so the app does not occupy the taskbar and the tray at the same time.BalloonTipTitle,BalloonTipText,BalloonTipIcon: the title, body text, and severity icon of the balloon notification shown byShowBalloonTip.
In the Properties window, assign an .ico file to Icon and leave Visible set to False to start:
Then set the text properties when the form loads. In the Form1_Load handler, assign notifyIcon1.BalloonTipTitle = "System Tray", notifyIcon1.BalloonTipText = "Some Notification", and notifyIcon1.Text = "System Tray App". The runnable program in the next section shows the complete Form1_Load method in context.
The full member list is documented in the NotifyIcon API reference.
Hide and restore the form
Here is the step-by-step procedure. The three handlers — Form1_Load, Form1_Resize, and notifyIcon1_MouseDoubleClick — are members of the Form1 partial class that the Visual Studio designer wires to events; they compile and run inside a Windows Forms project on Windows rather than as a standalone program.
-
Open Visual Studio and select
Create a new projectfrom the start window:
-
Choose the
Windows Forms Apptemplate and clickNext:
-
Type a project name and click
Create:
-
Drag
NotifyIconfrom the Toolbox onto the form, then assign itsIconand leaveVisibleset toFalseas described in the previous section. If you skip the icon, nothing will appear in the system tray when the form hides. -
Wire the form’s
Resizeevent. Select the form, open the event list in the Properties window (the lightning-bolt button), and double-clickResizeto createForm1_Resize:
-
Wire
notifyIcon1’sMouseDoubleClickevent the same way — selectnotifyIcon1in the component tray, open the event list, and double-clickMouseDoubleClickto createnotifyIcon1_MouseDoubleClick. -
Fill in the three handlers. They are shown in context in the runnable program below: in Visual Studio, paste just the
Form1_Load,Form1_Resize, andnotifyIcon1_MouseDoubleClickmethods intoForm1.cs.
Because the handlers depend on System.Windows.Forms types that only exist inside a Windows Forms project, the program below wraps them in small stand-in types (FormWindowState, MouseEventArgs, NotifyIcon) with the same member names so it compiles and runs on its own. Main plays the role of the user: it minimizes the window, lets Resize react, and then double-clicks the tray icon. Run this example:
using System;
// Minimal stand-ins so the handler logic compiles and runs as a plain
// console program. In a real project these types come from
// System.Windows.Forms and the handlers live in the Form1 partial class.
enum FormWindowState { Normal, Minimized }
class MouseEventArgs { }
class NotifyIcon
{
public bool Visible;
public string Text;
public string BalloonTipTitle;
public string BalloonTipText;
public void ShowBalloonTip(int timeout)
{
Console.WriteLine("Balloon tip: " + BalloonTipTitle + " - " + BalloonTipText);
}
}
class Form1
{
FormWindowState WindowState = FormWindowState.Normal;
NotifyIcon notifyIcon1 = new NotifyIcon();
void Hide() { Console.WriteLine("Form hidden"); }
void Show() { Console.WriteLine("Form shown"); }
private void Form1_Load(object sender, EventArgs e)
{
notifyIcon1.BalloonTipTitle = "System Tray";
notifyIcon1.BalloonTipText = "Some Notification";
notifyIcon1.Text = "System Tray App";
}
private void Form1_Resize(object sender, EventArgs e)
{
if (WindowState == FormWindowState.Minimized)
{
this.Hide();
notifyIcon1.Visible = true;
notifyIcon1.ShowBalloonTip(1000);
}
else if (FormWindowState.Normal == this.WindowState)
{
notifyIcon1.Visible = false;
}
}
private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
{
this.Show();
notifyIcon1.Visible = false;
WindowState = FormWindowState.Normal;
}
static void Main()
{
Form1 form = new Form1();
form.Form1_Load(null, new EventArgs());
form.WindowState = FormWindowState.Minimized;
form.Form1_Resize(null, new EventArgs());
form.notifyIcon1_MouseDoubleClick(null, null);
form.Form1_Resize(null, new EventArgs());
}
}
Form hidden
Balloon tip: System Tray - Some Notification
Form shown
Resize fires whenever WindowState changes, so it is the right place to react to minimization. this.Hide() removes the form’s taskbar button entirely — a plain minimize would only shrink it there. Making the icon Visible and calling ShowBalloonTip announces the move; the 1000 argument is the balloon’s display time in milliseconds. The else if branch hides the icon again whenever the window returns to Normal, which also covers restores that do not come through the tray icon.
In the restore handler, this.Show() brings the hidden form back, WindowState = FormWindowState.Normal un-minimizes it, and the icon is hidden again now that the form has its taskbar button.
Test the tray behavior
Run the application (F5). The blank Form1 window appears:
At this point the app occupies the taskbar and nothing has been added to the system tray yet:
Click the form’s minimize button:
The Form1_Resize handler fires: the form and its taskbar button disappear, the icon appears in the system tray, and the balloon tip pops up with the configured title and text — the same sequence the runnable program above prints as its three output lines:
Double-click the tray icon to confirm the restore path: the form reappears in its normal state, its taskbar button returns, and the tray icon disappears. The application keeps running throughout — minimizing to the tray only changes where it is displayed, not whether it executes.
If the icon never appears after minimizing, check that Icon was assigned in the designer or in code. NotifyIcon renders nothing (and ShowBalloonTip shows nothing) without an icon, which leaves the hidden app running with no visible way to restore it.