Introduction
This article was prompted by a question in Quick Answers about how to write a C# application that started in the tray. This article is meant to remedy that situation.
The Theory
As C# programmers know, applications start with a call to
System.Windows.Forms.Application.Run. This call is normally hidden from C# programmers, with the compiler supplying the required code behind the scenes. It is possible to call this explicitly, however, which allows us to write applications that do not rely on start-up forms.
AppContext Class
The first step is to create a class that inherits from the
System.Windows.Forms.ApplicationContext. This provides the information needed by the operating system to manage your application. This is also where you instantiate your
NotifyIcon for the tray, a menu to interact with your icon and any other essentials.
#region Storage
private NotifyIcon Tray;
private ContextMenuStrip MainMenu;
private ToolStripMenuItem mnuDisplayForm;
private ToolStripSeparator mnuSep1;
private ToolStripMenuItem mnuExit;
#endregion
#region Constructor
public AppContext()
{
//Initialize the menus
mnuDisplayForm = new ToolStripMenuItem("Display form");
mnuDisplayForm.Click += new System.EventHandler(mnuDisplayForm_Click);
mnuSep1 = new ToolStripSeparator();
mnuExit = new ToolStripMenuItem("Exit");
mnuExit.Click += new System.EventHandler(mnuExit_Click);
MainMenu = new ContextMenuStrip();
MainMenu.Items.AddRange(new ToolStripItem[] { mnuDisplayForm, mnuSep1, mnuExit });
//Initialize the tray
Tray = new NotifyIcon();
Tray.DoubleClick += new System.EventHandler(Tray_DoubleClick);
Tray.Icon = Properties.Resources.rap;
Tray.ContextMenuStrip = MainMenu;
Tray.Text = "Tray application";
//Display
Tray.Visible = true;
}
#endregion
#region Event handlers
private void AppContext_ThreadExit(object sender, System.EventArgs e)
{
//Guarantees that the icon will not linger.
Tray.Visible = false;
}
private void mnuDisplayForm_Click(object sender, System.EventArgs e)
{
OtherMethods.ShowDialog();
}
private void mnuExit_Click(object sender, System.EventArgs e)
{
OtherMethods.ExitApplication();
}
private void Tray_DoubleClick(object sender, System.EventArgs e)
{
OtherMethods.ShowDialog();
}
#endregion
OtherMethods Module
The methods ExitApplication and ShowDialog I put in a separate code file.
public static void ShowDialog()
{
if ((PF != null)&& ! PF.IsDisposed)
{
return;
}
bool CloseApp = false;
PF = new PopupForm();
PF.ShowDialog();
CloseApp = PF.DialogResult == DialogResult.Abort;
PF = null;
if (CloseApp)
{
Application.Exit();
}
}
It is tagged as Friend to prevent it from being exported. ExitApplication is where you would clean up any objects that are external to AppContext. Your application shuts down with the call to Application.Exit, which triggers AppContext's ThreadExit event. If you have any open forms, Application.Exit will close those down, exactly as you would expect.
ShowDialog displays a simple dialog box that allows the user to either cancel the form or close the application. I had to do a bit of extra work to guarantee that one and only one dialog box gets displayed: clicking mnuDisplayForm will happily spawn multiple forms otherwise.
Main Method
The next step is to actually write the code that launches your application. In a public module, simply declare one of four variations of the Main method.
Application.EnableVisualStyles();
//Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new AppContext());
In most cases, version 1 will be sufficient. If you need access to the command line then you will want to use version 2. Versions 3 and 4 allow you to return an integer value to the operating system when your application closes, which is useful only in rare situations.
Conclusion
I hope you found this article useful; if so, please vote it up. And if you find any bugs, please let me know below and I will try to get them fixed.
,
This attachment is hidden for guests. Please log in or register to see it.