inHere logo
Why do you want to go today?
Click here to go to back to HomeYou are in Programming sectionClick here to go to Projects sectionClick here to go to Misc section
Home » Programming » Visual Basic » Tray Icon control [Sept, 22 1999]

 

Prologue 
Platform : VB 6.

Since the first time I use VB 5 in Windows 95, I always wondering How do I add an Icon in the task bar like other cool application does? I've been looking for ActiveX object on the net but none satisfied me (Well some of them did, but their price was unbelievable). I started to read Windows SDK to get more information and I realized that Windows Shell already provide interface for Task Bar.

What we're going to do now is creating our own User control for Tray Icon. I've tried to find the easiest way to implement it in Visual Basic to avoid GPF or other unpleasant things happening. You won't need to redirect windows callback function or sub classing technique (as I did for several cases with VB). We will use the simplest solution but yet elegant.

 

Implementation
Designing our own Tray Icon control

Let's think about our user control. 

  • There's no need for this control to be visible at run time because it will only provide interface to add, modify and remove icon, so we're going to set the InvisibleAtRuntime to true.
  • We need Tooltip text for the icon tooltip. That makes we need ToolTip string property for our control.
  • What about the icon? Yes, we need it to. We're going to expose Picture property of the Usercontrol and we're going to pass it to the task bar. To let the user now the icon image, we will display it by drawing it over our control at design time.
  • It will have static size depending on the icon size.

To notify the Form that contains our control we have to provide custom event. Here are some examples.

Public Event OnLeftButtonDown(Shift As Integer)
Public Event OnRightButtonDown(Shift As Integer)

Shift value will indicates keyboard status.

Our control should expose interfaces for showing and hiding Tray Icon. 

Public Sub Show()
Public Sub Hide()

That's it. Now we have to look deep with the real work using the API.

Shell_NotifyIcon(...) API

The first you have to know is the interface to make the whole thing works. 

Public Function Shell_NotifyIcon(ByVal dwMessage, lpData as NOTIFYICONDATA) as Long

dwMessage, this message parameter will tell the task bar what to do. There are 3 constants for this message:

  • NIM_ADD, add icon to task bar.
  • NIM_DELETE, remove icon from task bar.
  • NIM_MODIFY, modify icon in task bar.

lpData, this is a reference to NOTIFYICONDATA structure that holds the information for our tray icon. The task bar will use the data for adding, modify or removing the icon.

NOTIFYICONDATA structure

NOTIFYICONDATA has 7 members:

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

cbSize, the size of the structure. You can get this by using VB's Len() function.

hWnd, window handle that will recieve the notification callback from taskbar.

uID, ID for our icon, any integer value will do.

uFlags, array of flags that holds information for out icon data.

  • NIF_ICON, indicates the hIcon member is valid.
  • NIF_MESSAGE, the uCallbackMessage member is valid.
  • NIF_TIP, the szTip member is valid.

uCallbackMessage, the callback message we will receive whenever user click or double click or icon.

hIcon, handle to icon.

szTip, null terminated string for tooltip.

Callback Message

When ever there's an event occured upon our icon such as mouse click or double click, the system will send notification message, the one that we registered with the NOTIFYICONDATA structure, and we should response to it. 

With Visual Basic, to handle User defined messages you have to change your windows message handler with sub classing technique. But what if we use system message instead? But we have to be really carefull choosing the right message or your window might misinterpreted the message and unpleasant thing will occured. 

Since we're going to create our own user control and there will be no message taken in our user control we will use WM_MOUSEMOVE message for our notification message. System will send the notification message through b value which is X and Y in Visual Basic MouseMove event. We only need the X value since it is reside in the lower word of LPARAM. But the problem is the X value represented in Visual Basic twips caling mode. To get the original value we can divide-integer it with Screen.TwipsPerPixelX.

   value = x \ Screen.TwipsPerPixelX

And then all we need to do is check the value and raise our custom event.

Private Sub UserControl_MouseMove(Button As Integer, Shift As Integer, _
                                   
x As Single, y As Single)
    Dim
value as Integer

   
value = x \ Screen.TwipsPerPixelX
    Select Case
value
        Case WM_LBUTTONDOWN
            RaiseEvent OnTrayLeftButtonDown(Shift)
        Case WM_RBUTTONDOWN
            RaiseEvent OnTrayRightButtonDown(Shift)    
    End Select
End
S
ub

Showing and Hiding Tray Icon

The implementation of Show() anf Hide method is very simple. Just examine the codes below:

Public Sub Show()
    Dim nid As NOTIFYICONDATA

    nid.cbSize = Len(nid)
    nid.hIcon = Picture
    nid.hwnd = UserControl.hwnd
    nid.szTip = m_strTips & vbNullChar
    nid.uCallbackMessage = WM_MOUSEMOVE
    nid.uFlags = NIF_ICON + NIF_MESSAGE + NIF_TIP
    nid.uID = 1000

    Call Shell_NotifyIcon(NIM_ADD, nid)
End Sub

Public Sub Hide()
    Dim nid As NOTIFYICONDATA

    nid.cbSize = Len(nid)
    nid.hIcon = Picture
    nid.hwnd = UserControl.hwnd    
    nid.szTip = m_strTips & vbNullChar
    nid.uCallbackMessage = WM_MOUSEMOVE
    nid.uFlags = NIF_ICON Or NIF_MESSAGE Or NIF_TIP
    nid.uID = 1000

    Shell_NotifyIcon NIM_DELETE, nid
End Sub

 

Epilogue

We've done it! That's all it takes to build our control. Well, of course we need some extra works for Properties and Display stuff. But the main issue for our ActiveX control project is covered. You will have to go to Products and Download section to download example project files. Please read the disclaimer policy. If it isn't there, please wait for a couple of days. I'm still busy uploading stuff and building my web site when I write this article. I hope this article will come handy for you.

Benni Adham 


Home | inHere | Products | Projects | Programming Stuff
Sign guest book | View guest book | about me | comments

Copyright © 1999 AdNet®. All rights reserved. AdNet® is registered to Benni Adham.