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

AID: 2729
  • Status: Published

12183 points

  • ByIdle_Mind
  • TypeTutorial
  • Posted on2010-03-24 at 23:09:35
Awards
  • Community Pick
  • Experts Exchange Approved

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 Application


01-WinFormsProject.jpg
  • 69 KB
  • Start with a standard WinForms Project
Start with a standard WinForms Project



2

Project Properties

Click on Project --> Properties


02-ProjectProperties.jpg
  • 28 KB
  • Click on Project --> Properties
Click on Project --> Properties



3

Change the Entry Point

Disable the Application Framework and set the "Startup Object"


03-StartupObject.jpg
  • 71 KB
  • Disable the Application Framework and Change 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)


04-AddIconToResources.jpg
  • 74 KB
  • Add the Icon for you NotifyIcon to the Resources Tab
Add the Icon for you NotifyIcon to the Resources Tab



5

Embed the Icon

Change the Persistence Mode of the Icon to Embedded


05-PersistenceEmbedded.jpg
  • 81 KB
  • Change the Persistence Mode of the Icon
Change the Persistence Mode of the Icon



6

Add Module

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


06-AddModule.jpg
  • 24 KB
  • Add a Module to the Project
Add a Module to the Project



7

(Optional) Remove Form1

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


07-DeleteForm1.jpg
  • 32 KB
  • Optionally Delete the default Form if you don't need it
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

                                  
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:

Select allOpen 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:


08-TrayIconWithToolTip.jpg
  • 11 KB
  • The NotifyIcon in the System Tray displaying its ToolTip
The NotifyIcon in the System Tray displaying its ToolTip


09-TrayIconWithContextMenuStrip.jpg
  • 12 KB
  • The NotifyIcon in the System Tray displaying its ContextMenuStrip
The NotifyIcon in the System Tray displaying its ContextMenuStrip
    Asked On
    2010-03-24 at 23:09:35ID2729
    Tags

    ApplicationContext

    ,

    NotifyIcon

    ,

    WinForms

    ,

    Visual Basic.Net

    Topic

    Microsoft Visual Basic.Net

    Views
    6049

    Comments

    Expert Comment

    by: DanRollins on 2010-03-25 at 00:43:10ID: 11713

    Excellent article!  You made it sound so easy (and showed that it is :-)
    You got my Yes vote!

    Expert Comment

    by: TheLearnedOne on 2010-03-25 at 05:36:14ID: 11744

    Mike, sometimes, I wonder just how idle your mind really  is!! *WINK*  There is something subtle, yet powerful, in this article about the ApplicationContext, which is the glue that pulls all the pieces together in one simple line:

         Application.Run(New MyContext)

    Thanks!!

    Bob

    Expert Comment

    by: Vishnukumar on 2010-03-28 at 11:53:15ID: 12046

    This article rocking.. This is what i need for my application.

    Expert Comment

    by: PaulHews on 2010-04-03 at 09:45:51ID: 12620

    Great article and very useful!  

    Expert Comment

    by: jpaulino on 2010-04-20 at 11:49:01ID: 13537

    Great article Idle_Mind!

    Expert Comment

    by: RIAS on 2010-04-22 at 07:24:16ID: 13696

    Thanks for the article.One of the best article I ever read.
    As always brilliant and truly Genius IDLE_MIND.

    Expert Comment

    by: pxj05 on 2010-05-17 at 07:46:07ID: 14662

    X E Lent. Works in VS 2005 as well.

    Expert Comment

    by: Shahan_Developer on 2010-06-14 at 05:54:09ID: 15700


    Idle_Mind great Article. Thanks for sharing it.
    I think the rumor is not rumor it is reality. ;)  just kidding

    Expert Comment

    by: JackOfPH on 2010-06-30 at 16:38:09ID: 16388

    Thanks, very useful.

    Great Article...

    Expert Comment

    by: IssacJones on 2011-10-14 at 02:14:27ID: 32409

    Hi guys

    Thanks for all your comments unfortuntately all seem to have a problem in that if "Enable application framework" is unchecked then the Splash Screen I have added is not called and displayed.

    Any ideas?

    Issac

    Add your Comment

    Please Sign up or Log in to comment on this article.

    Loading Advertisement...

    Top Visual Basic.NET Experts

    1. CodeCruiser

      461,941

      Wizard

      0 points yesterday

      Profile
      Rank: Genius
    2. kaufmed

      73,124

      Master

      3,000 points yesterday

      Profile
      Rank: Genius
    3. Masteraco

      68,140

      Master

      0 points yesterday

      Profile
      Rank: Guru
    4. Idle_Mind

      41,742

      10 points yesterday

      Profile
      Rank: Savant
    5. JamesBurger

      41,252

      0 points yesterday

      Profile
      Rank: Sage
    6. emoreau

      32,448

      500 points yesterday

      Profile
      Rank: Genius
    7. TheLearnedOne

      28,812

      0 points yesterday

      Profile
      Rank: Savant
    8. RolandDeschain

      24,308

      0 points yesterday

      Profile
      Rank: Sage
    9. nepaluz

      24,150

      20 points yesterday

      Profile
      Rank: Wizard
    10. MlandaT

      19,412

      0 points yesterday

      Profile
      Rank: Sage
    11. Stephan_Schrandt

      17,036

      0 points yesterday

      Profile
      Rank: Guru
    12. navneethegde

      14,932

      0 points yesterday

      Profile
      Rank: Wizard
    13. ddayx10

      14,000

      0 points yesterday

      Profile
      Rank: Sage
    14. gman84

      10,270

      0 points yesterday

      Profile
    15. tommyBoy

      9,850

      0 points yesterday

      Profile
      Rank: Sage
    16. nishantcomp2512

      9,450

      0 points yesterday

      Profile
      Rank: Guru
    17. vbigham

      9,100

      0 points yesterday

      Profile
      Rank: Master
    18. Cluskitt

      8,600

      0 points yesterday

      Profile
      Rank: Wizard
    19. AhmedHindy

      8,200

      0 points yesterday

      Profile
    20. matthewspatrick

      7,100

      0 points yesterday

      Profile
      Rank: Savant
    21. angelIII

      6,800

      0 points yesterday

      Profile
      Rank: Elite
    22. Dhaest

      6,684

      0 points yesterday

      Profile
      Rank: Genius
    23. AndyAinscow

      5,488

      0 points yesterday

      Profile
      Rank: Genius
    24. rick_gwu

      5,200

      0 points yesterday

      Profile
      Rank: Wizard
    25. Cenjoy100

      5,068

      0 points yesterday

      Profile

    Hall Of Fame