Creating Applications with NotifyIcon in Windows Forms
by Jessica Fosler
Overview
This article explains how to implement
the common features required of a notification-based application in Windows Forms:
starting up a Windows Forms application without showing a Form, using the NotifyIcon,
bringing an existing Form to the front of the desktop, and closing the Form on minimize.
The accompanying sample is a Calendar
application. By double clicking on the notify icon, a simple form containing a month
calendar appears. There is a context menu with “Show Calendar” and “Exit” menu items.
This article walks through the implementation of the sample.
Creating the NotifyIcon UI
Classes we’ll
need
-
System.Windows.Forms.NotifyIcon
-
System.Windows.Forms.ContextMenu
-
System.Windows.Forms.MenuItem
For this application, we’ll need
to create a new NotifyIcon, ContextMenu, and a few MenuItems
for the ContextMenu. The icon is set, and the NotifyIcon is set to Visible = true.
The NotifyIcon.Text property is used in order to display a ToolTip on mouse hover.
// add context menu with
“Show Calendar” and “Exit”
this.calendarNotifyIcon.ContextMenu
= calendarNotifyIconContextMenu;
// subscribe to the double
click event so we can show the calendar
this.calendarNotifyIcon.DoubleClick
+= new
EventHandler(this.calendarNotifyIcon_DoubleClick);
// add a custom icon for
the notify icon to display
this.calendarNotifyIcon.Icon
= new Icon(…);
// set the tooltip for the
notify icon
this.calendarNotifyIcon.Text
= DateTime.Now.ToLongDateString();
// tell the notify icon
to make itself visible
this.calendarNotifyIcon.Visible
= true;
Creating the CalendarForm
The CalendarForm is a simple Form
with a MonthCalendar filled inside of it. The MaximizeBox has been turned off for
the form (as it is as large as the calendar likes to be) and Minimimum and Maximum
sizes have been set for the form.
Starting the application without
showing a form
So far, so great, but we haven’t yet solved the Main challenge: starting the application
without showing a form.
Let’s take a step back and look at how the first line of code in our program actually
works: Application.Run.
Dissecting
Application.Run
If you have created a Windows Forms
application, you may have happened across this line in Main:
Application.Run(new Form1());
Magically, after calling this,
the Form appears and events start firing left and right. Here’s what is actually
happening, not quite so magically:
//Taking a microscope to Application.Run
–
//create the form, and call initialize
component
Form1 form1 = new Form1();
// create an application context
ApplicationContext applicationContext
= new ApplicationContext();
// Set applicationContext.MainForm
so that
// when form1 closes, exit the
application context
applicationContext.MainForm =
form1;
// Call Application.Run which
will
// - call applicationContext.MainForm.Show()
// - begin processing events
Application.Run(applicationContext);
From this code, we can intuit that
the ApplicationContext defines when the Application should exit. For regular windows
applications, this model works well, but for notification-based applications, we’ll
need to do something else. The solution: a custom ApplicationContext.
Creating a
custom ApplicationContext
Creating a custom application context
is super simple.
ApplicationContext applicationContext
= new ApplicationContext();
Application.Run(applicationContext);
The only problem with the above
two lines of code is that it shows nothing (we haven’t created a form or anything)
and runs forever (we haven’t defined when the application should end). It’s likely
this is not desired behavior.
- To exit the
application, we’ll need to figure out when to call applicationContext.ExitThread.
- To bring
up some sort of UI, we’ll need to do something interesting before calling Application.Run.
The simplest approach is to create
the UI, hold onto the ApplicationContext and call ExitThread on it as a result of
UI interaction. For our notification-based application, this will not work
well, as we will want to keep the NotifyIcon UI separate (which will stick around
all the time) from the form that we want to create and show (whenever the user clicks
on the icon.)

In order to maintain this separation,
let’s associate the NotifyIcon UI with the ApplicationContext, and create the Form
on demand. In order to do this, we will create a class that inherits from ApplicationContext,
create the notify icon UI and exit the application when the user selects the exit
option from the notify icon’s context menu.
The CalendarApplicationContext
Class
Here is an overview of the methods
we’ll need to create in our custom CalendarApplication class.

Showing the Form
In order to
show the calendar when the context menu item is clicked or the notify icon is double
clicked; we will create a single method called ShowForm and call it from both places.
Creating the form
If there is
no form currently displayed, the function creates a new Form and calls Show().
There are
a few bookkeeping details to take into account: we want to show one form at a time,
so we’ll save the Form off into a mainForm member variable. When the Form closes,
we’ll go ahead and clear off this member so we remember to create a fresh new form
the next time we’re asked.
Bringing existing forms to front
If the user selects “Show Calendar”
again, it’s likely that the window is lost behind other windows, and they would
like to make it visible again. If there is currently a mainForm, we call mainForm.Activate
to bring it to the front of the Z-Order.
ShowForm implementation
/// <summary>
/// This function will either
create a new CalendarForm or activate the /// existing one, bringing the window
to front.
/// </summary>
private void ShowForm()
{
if (mainForm == null)
{
// create a fresh new CalendarForm
and show it.
mainForm = new CalendarForm();
mainForm.Show();
// hook onto the closed
event so we can null out the
// main form... this avoids
reshowing
// a disposed form.
mainForm.Closed +=new EventHandler(mainForm_Closed);
}
else
{
// the form is currently
visible, go ahead and bring it to
// the front so the user
can interact
mainForm.Activate();
}
}
private void mainForm_Closed (object
sender, EventArgs e)
{
// null out the main form so we
know to create a new one.
this.mainForm = null;
}
Handling Exit
When the user
selects the Exit context menu item, the click event handler for Exit calls
ExitThread. If there is a mainForm currently being
displayed, we override ExitThreadCore to clean it
up by calling dispose on it.
CalendarApplicationContext Exit
implementation
/// <summary>
/// When the exit menu item
is clicked, make a call to terminate the /// ApplicationContext.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void exitContextMenuItem_Click(object
sender, EventArgs e)
{
ExitThread(); // this will
call ExitThreadCore
}
/// <summary>
/// If we are presently
showing a mainForm, clean it up.
/// </summary>
protected override void
ExitThreadCore()
{
if (mainForm != null)
{
// before we exit, give
the main form a chance
//to clean itself up.
mainForm.Close();
}
base.ExitThreadCore ();
}
Implementing Close on Minimize
Another common feature of notification-based
applications is closing the form on Minimize. Thankfully the WindowState
property off of Form tells us the current Min/Max state of the form, so in the CalendarForm
class we can just go ahead and sync the SizeChanged event and call close.
private void CalendarForm_SizeChanged(object
sender, EventArgs e)
{
if (this.WindowState == FormWindowState.Minimized)
{
this.Close();
}
}
Putting it all together
Create a class called CalendarForm
that contains MonthCalendar. In Main, replace the Application.Run(new CalendarForm())
with our new ApplicationContext:
CalendarApplicationContext applicationContext
=
new CalendarApplicationContext();
Application.Run(applicationContext);
The constructor creates the notify
icon, and the CalendarForm is created on demand.
A final note
Obviously, a calendar application
should strive to keep current with the date. A System.Windows.Forms.Timer can be
used to update the date/time on the tooltip for the NotifyIcon and the CalendarForm.