Page 1 of 1

Adding A Notify Icon in VB6 Rate Topic: ***** 1 Votes

#1 PsychoCoder  Icon User is offline

  • Google.Sucks.Init(true);
  • member icon

Reputation: 1641
  • View blog
  • Posts: 19,853
  • Joined: 26-July 07

Post icon  Posted 11 February 2008 - 01:25 PM

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:


#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:


'**************************************************************************
'* 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:


'**************************************************************************
'* 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:


'**************************************************************************
'* 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:


'**************************************************************************
'* 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:


'**************************************************************************
'* 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:


'**************************************************************************
'* 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:


'**************************************************************************
'* 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:


'**************************************************************************
'* 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:


'**************************************************************************
'* 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:


'**************************************************************************
'* 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:


'**************************************************************************
'* 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:


'**************************************************************************
'* 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:


'**************************************************************************
'* 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:


'**************************************************************************
'* 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:


'**************************************************************************
'* 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:


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:


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:


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: 3639

Is This A Good Question/Topic? 1
  • +

Replies To: Adding A Notify Icon in VB6

#2 GrahamP  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 01-July 08

Posted 01 July 2008 - 11:34 AM

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?
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1