<

Building a Formless WinForms Application with a NotifyIcon in VB.Net 2008

Published on
38,460 Points
24,160 Views
13 Endorsements
Last Modified:
Awarded
Community Pick
This tutorial demonstrates one way to create an application that runs without any Forms but still has a GUI presence via an Icon in the System Tray.

The magic lies in Inheriting from the ApplicationContext Class and passing that to Application.Run() instead of a Form instance.  With this approach we automatically get a built-in message pump and do not see any ugly Console windows.  Having a message pump means that an infinite loop is not necessary to keep the app "alive".  It also means that we can freely create Controls and Forms at run-time and respond to their events as usual.  We can even elegantly multi-thread the application by using a BackgroundWorker() Control from within the Inherited ApplicationContext Class.

Why would you want to do this?  Perhaps you have a "background" operation that needs to run all the time and would like to give the user a way to interact with the application.  The tray icon gives you the option to display menus or simply popup a configuration dialog if clicked.  This is an easy approach compared to implementing a full blown service.

The ApplicationContext provides complete freedom in controlling when the program is closed.  You are no longer constrained to just the two shutdown mode choices of "When startup form closes" or "When last form closes".  With no "startup form" you can now freely switch between forms without worrying about the app closing on you.  You can display a Login form and then actually completely close it before moving on to the Main form.  No more need to show the Main form with ShowDialog() or keep the Login form hidden just to keep the app alive!  Shared variables in the ApplicationContext class can be used to store information that the entire program needs access to (such as privilege levels).  Since the app only shuts down when you explicitly call Application.Exit() you can build a program that only closes when the conditions are right for your particular scenario.

Note that this technique can also be used without any GUI elements at all!  The app will happily run without any interface and will still have a message pump making it easier to work with than a Console app.

Let's get started:

1. Project Type

Start with a standard WinForms ApplicationStart with a standard WinForms Project

2. Project Properties

Click on Project --> PropertiesClick on Project --> Properties

3. Change the Entry Point

Disable the Application Framework and set the "Startup Object"Disable the Application Framework and Change the "Startup Object"

4. Add Tray Icon

Switch to the Resources Tab and add your Icon File (.ico)Add the Icon for you NotifyIcon to the Resources Tab

5. Embed the Icon

Change the Persistence Mode of the Icon to EmbeddedChange the Persistence Mode of the Icon

6. Add Module

Add a Module to the Project.  Leave the default name, Module1Add a Module to the Project

7. ([b]Optional[/b]) Remove Form1

Delete the default Form if you don't need it
(Forms can still be used in the application if you desire!)Optionally Delete the default Form if you don't need it

8. Add Code

Replace the code in the Module with the listing below.
Important! Change "My.Resources.Happy" in line #17 so that it correctly reflects the name of your Embedded Icon
Module Module1

    Public Sub Main()
        Application.Run(New MyContext)
    End Sub

End Module

Public Class MyContext
    Inherits ApplicationContext

    Private WithEvents TrayIcon As New NotifyIcon
    Private WithEvents CMS As New ContextMenuStrip
    Private WithEvents ExitMenu As New ToolStripMenuItem("Exit")

    Public Sub New()
        TrayIcon.Icon = My.Resources.Happy
        TrayIcon.Text = "ApplicationContext with a NotifyIcon" ' <-- Tooltip on the NotifyIcon
        TrayIcon.Visible = True

        CMS.Items.Add(ExitMenu)
        TrayIcon.ContextMenuStrip = CMS

        ' You can add a BackgroundWorker control to the class and start a lengthy process from here...
    End Sub

    Private Sub CMS_Opening(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles CMS.Opening
        ' From this event you can control which menu items appear (visibility or disabled) or 
        ' even cancel the event and prevent the context menu from appearing at all
    End Sub

    Private Sub ExitMenu_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles ExitMenu.Click
        Application.Exit()
    End Sub

    Private Sub MyContext_ThreadExit(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.ThreadExit
        TrayIcon.Visible = False
    End Sub

End Class

Open in new window


9. Test it out!

Run the Project
Hopefully you'll get an Icon in the System Tray that has an "Exit" option when you Right Click it

In the images below, the Happy face is the icon being displayed by the application:The NotifyIcon in the System Tray displaying its ToolTipThe NotifyIcon in the System Tray displaying its ContextMenuStrip
13
Ask questions about what you read
If you have a question about something within an article, you can receive help directly from the article author. Experts Exchange article authors are available to answer questions and further the discussion.
Get 7 days free