Chat LIVE With Programming Experts! There Are 23 Online Right Now...

Welcome to Dream.In.Code
Become an Expert!

Join 244,202 Programmers for FREE! Get instant access to thousands of experts, tutorials, code snippets, and more! There are 1,461 people online right now. Registration is fast and FREE... Join Now!




Adding A Notify Icon in VB6

 
Reply to this topicStart new topic

> Adding A Notify Icon in VB6

Rating  5
PsychoCoder
Group Icon



post 11 Feb, 2008 - 12:25 PM
Post #1


Welcome to my tutorial on Adding A Notify Icon in VB6. In this tutorial we will be discussing how to add a system tray icon to your application, and how to get it react to events as right-click, left-click, double-click, how to change the icon at runtime, say you're running a process and you want the icon to be an hourglass, this tutorial will show you how to accomplish that.

Before starting this tutorial, I am assuming you have a firm understanding of Win32 API calls in VB6, user defined data types, and hooking into the Windows API to catch mouse click and such. This tutorial is fairly advanced, and if you haven't worked with these items I would suggest some more beginner tutorials before attempting this one.

Before we get to any code, to use this Class you need to have a form with a PictureBox named pickhook, with your ImageList loaded with the icons you wish to use. The class file will look for that ImageList with your icons, and those are the icons that will be placed in the system tray. Now to some code, which is the reason you're reading this tutorial.

The first thing in our class is a constant specifying the version of Visual Basic, this allows for backwards compatibility:


CODE

#Const VB_VERSION = 6



The next item in our class is a user defined type of NOTIFYICONDATA, this will hold all the data we need about our notify icon, its size, handle, icon and other such data:


CODE

'**************************************************************************
'* User Defined Types
'**************************************************************************
Private Type NOTIFYICONDATA
    cbSize As Long
    hwnd As Long
    uId As Long
    uFlags As Long
    ucallbackMessage As Long
    hIcon As Long
    szTip As String * 64
End Type


Next in our class is a series of Constants required by the Shell_NotifyIcon Win32 API. These will be used for various reasons, to add the icon, to remove the icon, to capture mouse moves and mouse clicks:


CODE

'**************************************************************************
'* Constants
'**************************************************************************
Private Const NIM_ADD = &H0
Private Const NIM_MODIFY = &H1
Private Const NIM_DELETE = &H2
Private Const WM_MOUSEMOVE = &H200
Private Const NIF_MESSAGE = &H1
Private Const NIF_ICON = &H2
Private Const NIF_TIP = &H4

Private Const WM_LBUTTONDBLCLK = &H203
Private Const WM_LBUTTONDOWN = &H201
Private Const WM_LBUTTONUP = &H202
Private Const WM_RBUTTONDBLCLK = &H206
Private Const WM_RBUTTONDOWN = &H204
Private Const WM_RBUTTONUP = &H205



Next we will add our Win32 API call for Shell_NotifyIcon, which is located in the shell32.dll:


CODE

'**************************************************************************
'* API Declarations
'**************************************************************************
Private Declare Function Shell_NotifyIcon Lib "shell32" Alias "Shell_NotifyIconA" (ByVal dwMessage As Long, pnid As NOTIFYICONDATA) As Boolean


As with most class files we will need some local variables, here we will have an instance of our NOTIFYICONDATA user defined type, a PictureBox and a variable for the tooltip:


CODE

'**************************************************************************
'* Local variables
'**************************************************************************
'Instance of our user defined type
Private t As NOTIFYICONDATA
'instance of our PictureBox. Use WithEvents so we have
''access to the properties, method & events of the control
Private WithEvents pichook As PictureBox
'Variable to hold the tool tip we will be passing
Private mvarToolTip As String


Next we will declare our public mouse Events, which we will raise later in the tutorial for acting on these mouse events:


CODE

'**************************************************************************
'* Events
'**************************************************************************
Public Event LButtonDblClk()
Public Event LButtonDown()
Public Event LButtonUp()
Public Event RButtonDblClk()
Public Event RButtonDown()
Public Event RButtonUp()



Now we will take a look at the properties we need for our notify icon class. Read/Write properties have a Let and a Set, Let will retrieve the property, Set will set the value of the property. We have properties for the tool tip to pass to the icon, the icon itself, a property telling the class what the default double-click action is, and finally a property for this source window, this is the Form that is calling the class and manipulating the notify icon:


CODE

'**************************************************************************
'* local variable(s) to hold property value(s)
'**************************************************************************
Private mvarSourceWindow As Form 'local copy
Private mvarDefaultDblClk As Boolean 'local copy

'**************************************************************************
'* Tooltip Property
'**************************************************************************
Public Property Let ToolTip(ByVal vData As String)
    ChangeToolTip vData
End Property

Public Property Get ToolTip() As String
    ToolTip = mvarToolTip
End Property

'**************************************************************************
'* Icon Property
'**************************************************************************
Public Property Let Icon(ByVal vData As Variant)
    ChangeIcon vData
End Property

Public Property Get Icon() As Variant
    Icon = t.hIcon      'pichook.Picture
End Property

'**************************************************************************
'* DefaultDblClk Property
'**************************************************************************
Public Property Let DefaultDblClk(ByVal vData As Boolean)
    mvarDefaultDblClk = vData
End Property

Public Property Get DefaultDblClk() As Boolean
    DefaultDblClk = mvarDefaultDblClk
End Property

'**************************************************************************
'* SourceWindow Property
'**************************************************************************
Public Property Set SourceWindow(ByVal vData As Form)
    Set mvarSourceWindow = vData
    SetPicHook
End Property

Public Property Get SourceWindow() As Form
    Set SourceWindow = mvarSourceWindow
End Property


In the SetSourceWindow Property, we call a procedure named SetPickHook. In this procedure we check the version of VB running and set our local variable pickhook, which is the PictureBox control on our source Form. We then hide the control, set it's current picture to the icon we name, and set the handle to the handle of the PictureBox control we're using:


CODE

'**************************************************************************
'* SetPicHook - Sets up the pichook control
'**************************************************************************
Private Sub SetPicHook()
    'tell where to go if an error occurs
    On Error GoTo AlreadyAdded
    'check the VB version so we know how to set the value
    'of our pickhook property
    #If VB_VERSION = 6 Then
        Set pichook = mvarSourceWindow.Controls.Add("VB.PictureBox", "pichook")
    #Else
        Set pichook = mvarSourceWindow.pichook
    #End If
        'hide the picturebox
        pichook.Visible = False
        'set its picture to the icon we determine
        pichook.Picture = mvarSourceWindow.Icon
        'set the handle, so we know what it is for
        'future calls
        t.hwnd = pichook.hwnd
        'exit the sub
        Exit Sub
    
AlreadyAdded:
        If Err.Number <> 727 Then  ' pichook has already been added
           MsgBox "Run-time error '" & Err.Number & "':" & vbCrLf & vbCrLf & Err.Description, vbCritical + vbOKOnly, "Error"
           Stop
           Resume
        End If
End Sub



Now, before we can raise any of the events we declared earlier, we need to initialize our class. In this procedure we will set the values of our NOTIFYICONDATA User Defined Type. So let's take a look at how we do this:


CODE

'**************************************************************************
'* Class Initialize
'**************************************************************************
Private Sub Class_Initialize()
    'Set the values of our user defined type
    
    'Set the default double click event to True
    '(this can be changed by the calling form)
    mvarDefaultDblClk = True
    t.cbSize = Len(t)
    t.uId = 1&
    t.uFlags = NIF_ICON Or NIF_TIP Or NIF_MESSAGE
    t.ucallbackMessage = WM_MOUSEMOVE
    t.hIcon = Me.Icon
    t.szTip = Chr$(0)       'Default to no tooltip
End Sub



If you remember earlier when we declared our local variables, when we declared the variable for the PictureBox Control we will be using on our Form, we declared it using the WithEvents Keyword. This allows us to raise our events based on the PictureBox Control's MouseMove Event.

In this procedure we will first determine the position of the mouse pointer to ensure we are clicking on the icon, not somewhere else. We will then determine which mouse button is being pressed, and based on this information we will raise the proper event:


CODE

'**************************************************************************
'* Mousemove event of the pichook control
'**************************************************************************
Private Sub pichook_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
    Static rec As Boolean, msg As Long, oldmsg As Long
    'set both equal to each other to override the last call
    oldmsg = msg
    msg = X / Screen.TwipsPerPixelX
  
    If rec = False Then
        rec = True
        'Determine which mouse button is pressed so
        'we can raise the proper event
        Select Case msg
            Case WM_LBUTTONDBLCLK:
                LButtonDblClk
            Case WM_LBUTTONDOWN:
                LButtonDblClk
            Case WM_RBUTTONDBLCLK:
                LButtonDblClk
            Case WM_RBUTTONDOWN:
                LButtonDblClk
        End Select
        rec = False
    End If
End Sub



For the purposes of this example, the only event we will be raising is the left mouse button click. When the user left clicks on the icon, the Form will be set to its normal state and shown, and the icon will be removed from the system tray. This code can be altered to show a menu when the user does a left click, with different options, like a Context Menu. Since Visual Basic 6 doesn't offer inheritance, we will use a variable to override the default left button click:


CODE

'**************************************************************************
'* Default LButtonDblClk event
'*
'* Since VB doesn't really have inheritance (&^$%#&*!!) we have to fake it by
'* using a variable to override default events...
'**************************************************************************
Private Sub LButtonDblClk()
    If mvarDefaultDblClk Then
        mvarSourceWindow.WindowState = vbNormal
        mvarSourceWindow.Show
        App.TaskVisible = True
        RemoveFromSysTray
    End If
    
    RaiseEvent LButtonDblClk
End Sub



The line App.TaskVisible = True will add our application back to the Task Manager list. Next we will take a look at procedures used to manipulate the system tray icon, such as removing it from the tray, adding it to the tray, minimizing your application to the system tray, changing the system tray icon, and finally changing the tool tip of the icon. First we will look at how we remove the icon from the system tray:


CODE

'**************************************************************************
'* RemoveFromSysTray - Call to remove the icon from the system tray
'**************************************************************************
Public Sub RemoveFromSysTray()
    t.cbSize = Len(t)
    t.hwnd = pichook.hwnd
    t.uId = 1&
    Shell_NotifyIcon NIM_DELETE, t
End Sub



The most important part of this procedure is the line Shell_NotifyIcon NIM_DELETE, t, here we pass the constant NIM_REMOVE and our instance of the NOTIFYICONDATA type, this will remove the icon from the system tray. To add the icon to the system tray, say when we minimize the form, we will call Shell_NotifyIcon and pass it the constant NIM_ADD, telling Windows to add the icon to the system tray:


CODE

'**************************************************************************
'* IconInSysTray - Call to place an icon in the system tray
'**************************************************************************
Public Sub IconInSysTray()
    Shell_NotifyIcon NIM_ADD, t
End Sub



When we minimize our application, we want to add the system tray icon, hide the application, then remove it from the Task Manager list. This will give the appearance that the application was minimized to the system tray:


CODE

'**************************************************************************
'* MinToSysTray - Call to minimize the application, remove it from the Task
'* manager, and place an icon in the system tray
'**************************************************************************
Public Sub MinToSysTray()
    'add the icon to the system tray
    Me.IconInSysTray
    'hide our window
    mvarSourceWindow.Hide
    'remove the application from the Task Manager
    App.TaskVisible = False
End Sub



Now we will look at how we can change the icon displayed at run-time. To accomplish this we pass the icon we want to display, we change the hIcon value of our NOTIFYICONDATA type, then call Shell_NotifyIcon passing the constant NIM_MODIFY to it, telling Windows to change our icon:


CODE

'**************************************************************************
'* ChangeIcon - Change the system tray icon
'**************************************************************************
Public Sub ChangeIcon(toNewIcon)
    Set pichook.Picture = toNewIcon
    t.hIcon = pichook.Picture
    Shell_NotifyIcon NIM_MODIFY, t
End Sub



The final procedure in our class is used to change the tooltip displayed when the mouse pointer hovers over the system tray icon. To accomplish this we pass the stirng we want displayed, we set the szTip value of our NOTIFYICONDATA type, we call Shell_NotifyIcon passing the constant NIM_MODIFY, telling Windows to change the ToolTip, then we make sure the Window is minimized before setting the ToolTip:


CODE

'**************************************************************************
'* ChangeToolTip - Change the systray icon tooltip
'**************************************************************************
Public Sub ChangeToolTip(ByVal cNewTip As String)
    mvarToolTip = cNewTip
    t.szTip = cNewTip & Chr$(0)
    Shell_NotifyIcon NIM_MODIFY, t
    If mvarSourceWindow.WindowState = vbMinimized Then
        mvarSourceWindow.Caption = cNewTip
    End If
End Sub



Now that we have all this code, I bet you're wondering how to use it. Well here we will show a couple examples of how to use this in our application. In your Form's code you will want to make a variable that references our class, in my case the class is called NotifyIcon, so I would do:


CODE

Private WithEvents icon As NotifyIcon



This now gives me a reference to my class. In the Form's Load Event is where I will set the properties of my Icon class:


CODE

Private Sub Form_Load()
    'create a new instance of our class
    Set icon = New NotifyIcon
    'set the source window to the current form
    Set icon.SourceWindow = Me
    'change the icon to an image in our ImageList control
    icon.ChangeIcon ImageList1.ListImages("newicon").Picture
    'set the tooltip
    icon.ToolTip = "This is our ToolTip"
End Sub



To give the affect of minimizing to the system tray when the form is minimized, we will do this in the Form's Resize Event:


CODE

Private Sub Form_Resize()
    If Me.WindowState = vbMinimized Then
        icon.MinToSysTray
    End If
End Sub



That is the end of this tutorial on Adding A Notify Icon in VB6. I will be including the class file for this tutorial for your use. The class is under the GNU General Public License, meaning you can modify and distribute the file as you see fit. I hope you found this tutorial useful and informative, and if you have any questions please post them here, as others may have the same questions as you, and I will get them answered as soon as possible. Thank you for reading.

Happy Coding!
Attached File  NotifyIcon.zip ( 2.83k ) Number of downloads: 826
Go to the top of the page
+Quote Post


Register to Make This Ad Go Away!

GrahamP
*



post 1 Jul, 2008 - 10:34 AM
Post #2
It is mentioned that the code can be altered to show a menu when the user does a left click, with different options, like a Context Menu. I don't know how to start. Any suggestions?
Go to the top of the page
+Quote Post


Reply to this topicStart new topic
2 User(s) are reading this topic (2 Guests and 0 Anonymous Users)
0 Members:

 


Lo-Fi Version Time is now: 7/4/09 07:28AM

Live Help!

Be Social

Dream.In.Code RSS Feed Dream.In.Code LinkedIn Group Follow Us On Twitter Fan Us On Facebook

Tutorials

Programming

Web Development

Reference Sheets

Code Snippets

DIC Chatroom

Bye Bye Ads

Monthly Drawing

Thumb Drive

Top Contributors

Top 10 Kudos This Month