System Tray and VB.NET

Last post 07-03-2009 7:56 by wix. 6 replies.
Page 1 of 1 (7 items)
Sort Posts: Previous Next
  • 09-15-2003 13:09

    System Tray and VB.NET

    Greetings,

    I've read Alex's fine MessageWindow Class article over on Microsoft's site (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetcomp/html/messagewindow.asp?frame=true)

    Since his original code was written in C#, I’ve went ahead and converted it over to VB for an application I am working on. However, I ran across one small problem that I was not able to resolve and I was hoping someone could provide some advise as to a resolution.

    Everything works fine expect in the WindowSink class where the Click event needs to be detected and raised. For some reason that escapes me, the notifyIcon object from the following code snippet does not recognize the public Click event from the parent class.

    If Not notifyIcon.Click Is Nothing Then
    RaiseEvent notifyIcon.Click(notifyIcon, Nothing)
    End If

    What might I be missing here? Attached is the complete code of the converted code.

    Thanks in advance

    Steve


    Imports System.Runtime.InteropServices

    Namespace NotifiyClient
    Public Class clsNotifyIcon
    Private winSink As WindowSink
    Private uID As Integer = 5000

    'Declare click event
    Public Event Click As System.EventHandler

    'Constructor
    Public Sub New()
    'Create instance of the MessageWindow subclass
    winSink = New WindowSink(Me)
    winSink.uID = uID
    End Sub

    Public Sub Add(ByVal hIcon As IntPtr)
    TrayMessage(winSink.Hwnd, NIM_ADD, Convert.ToUInt32(uID), hIcon)
    End Sub

    Public Sub Remove()
    TrayMessage(winSink.Hwnd, NIM_DELETE, Convert.ToUInt32(uID), IntPtr.Zero)
    End Sub

    Public Sub Modify(ByVal hIcon As IntPtr)
    TrayMessage(winSink.Hwnd, NIM_MODIFY, Convert.ToUInt32(uID), hIcon)
    End Sub

    Private Sub TrayMessage(ByVal hwnd As IntPtr, ByVal dwMessage As Integer, ByVal uID As System.UInt32, ByVal hIcon As IntPtr)
    Dim notdata As NOTIFYICONDATA = New NOTIFYICONDATA

    notdata.cbSize = 152
    notdata.hIcon = hIcon
    notdata.hWnd = hwnd
    notdata.uCallbackMessage = Convert.ToUInt32(WM_NOTIFY_TRAY)
    notdata.uFlags = Convert.ToUInt32(3)
    notdata.uID = uID

    Dim ret As Int32 = Shell_NotifyIcon(dwMessage, notdata)
    End Sub

    #Region "API Declarations "
    Private Const WM_LBUTTONDOWN = &H201

    'User defined message
    Private Const WM_NOTIFY_TRAY As Integer = &H400 + 2001

    Private Const NIM_ADD As Int32 = &H0
    Private Const NIM_MODIFY As Int32 = &H1
    Private Const NIM_DELETE As Int32 = &H2

    Private Structure NOTIFYICONDATA
    Friend cbSize As Integer
    Friend hWnd As IntPtr
    Friend uID As System.UInt32
    Friend uFlags As System.UInt32
    Friend uCallbackMessage As System.UInt32
    Friend hIcon As IntPtr
    End Structure

    <DllImport("coredll.dll")> _
    Private Shared Function Shell_NotifyIcon(ByVal dwMessage As Int32, ByRef pnid As NOTIFYICONDATA) As Int32
    End Function

    <DllImport("coredll.dll")> _
    Private Shared Function SetForegroundWindow(ByVal hWnd As IntPtr) As Int32
    End Function

    <DllImport("coredll.dll")> _
    Private Shared Function ShowWindow(ByVal hWnd As IntPtr, ByVal nCmdShow As Int32) As Int32
    End Function

    <DllImport("coredll.dll")> _
    Private Shared Function GetFocus() As IntPtr
    End Function
    #End Region

    #Region "WindowSink "
    Friend Class WindowSink
    Inherits Microsoft.WindowsCE.Forms.MessageWindow

    'Private members
    Private m_uID As Integer = 0
    Private notifyIcon As clsNotifyIcon

    'Constructor
    Public Sub New(ByVal notIcon As clsNotifyIcon)
    notifyIcon = notIcon
    End Sub

    Public WriteOnly Property uID() As Integer
    Set(ByVal Value As Integer)
    m_uID = Value
    End Set
    End Property

    Protected Overrides Sub WndProc(ByRef msg As Microsoft.WindowsCE.Forms.Message)
    If msg.Msg = WM_NOTIFY_TRAY Then
    If msg.LParam.ToInt32 = WM_LBUTTONDOWN Then
    If msg.WParam.ToInt32 = m_uID Then
    'If hooked, raise the event
    If Not notifyIcon.Click Is Nothing Then
    RaiseEvent notifyIcon.Click(notifyIcon, Nothing)
    End If
    End If
    End If
    End If
    End Sub
    End Class
    #End Region
    End Class
    End Namespace
  • 02-15-2004 18:16 In reply to

    Re: System Tray and VB.NET

    I needed a similar function for one of our applications with the difference that I wanted to be able to switch icons when needed to indicate different stati. Therefore I created a library that makes use of icons stored in resource dlls. If you want to try it out have a look at http://www.mozzak.com.

    Mozzak
  • 12-13-2004 18:22 In reply to

    Re: System Tray and VB.NET

    here is a way to use Alex's NotifyIcon class in your VB app. Instead of translating the whole thing to VB, I kept his NotifyIcon class in a seperate class, not changing anything, and kept it in c#. Create a class using vs.net, then build this DLL. You will add this DLL as a reference in your VB.net project.

    Here is the class:

    using System;
    using System.Runtime.InteropServices;
    using System.Windows.Forms;

    namespace NotifyClient
    {

    public class NotifyIcon
    {
    //Declare click event
    public event System.EventHandler Click;

    private WindowSink windowSink;
    private int uID = 5000;

    //Constructor
    public NotifyIcon()
    {
    //Create instance of the MessageWindow subclass
    windowSink = new WindowSink(this);
    windowSink.uID = uID;
    }

    //Destructor
    ~NotifyIcon()
    {
    Remove();
    }


    public void Add(IntPtr hIcon)
    {
    TrayMessage(windowSink.Hwnd, NIM_ADD, (uint)uID, hIcon);
    }

    public void Remove()
    {

    TrayMessage(windowSink.Hwnd, NIM_DELETE, (uint)uID, IntPtr.Zero);
    }

    public void Modify(IntPtr hIcon)
    {

    TrayMessage(windowSink.Hwnd, NIM_MODIFY, (uint)uID, hIcon);

    }



    private void TrayMessage(IntPtr hwnd, int dwMessage, uint uID, IntPtr hIcon)
    {
    NOTIFYICONDATA notdata = new NOTIFYICONDATA();

    notdata.cbSize = 152;
    notdata.hIcon = hIcon;
    notdata.hWnd = hwnd;
    notdata.uCallbackMessage = WM_NOTIFY_TRAY;
    notdata.uFlags = NIF_MESSAGE | NIF_ICON;
    notdata.uID = uID;

    int ret = Shell_NotifyIcon(dwMessage, ref notdata);
    }

    #region API Declarations

    internal const int WM_LBUTTONDOWN = 0x0201;
    //User defined message
    internal const int WM_NOTIFY_TRAY = 0x0400 + 2001;

    internal const int NIM_ADD = 0x00000000;
    internal const int NIM_MODIFY = 0x00000001;
    internal const int NIM_DELETE = 0x00000002;

    const int NIF_MESSAGE = 0x00000001;
    const int NIF_ICON = 0x00000002;


    internal struct NOTIFYICONDATA
    {
    internal int cbSize;
    internal IntPtr hWnd;
    internal uint uID;
    internal uint uFlags;
    internal uint uCallbackMessage;
    internal IntPtr hIcon;
    //internal char[] szTip = new char[64];
    //internal IntPtr szTip;
    }

    [DllImport("coredll.dll")]
    internal static extern int Shell_NotifyIcon(
    int dwMessage,ref NOTIFYICONDATA pnid);

    [DllImport("coredll.dll")]
    internal static extern int SetForegroundWindow(IntPtr hWnd);

    [DllImport("coredll.dll")]
    internal static extern int ShowWindow(
    IntPtr hWnd,
    int nCmdShow);

    [DllImport("coredll.dll")]
    internal static extern IntPtr GetFocus();

    #endregion


    #region WindowSink

    internal class WindowSink : Microsoft.WindowsCE.Forms.MessageWindow
    {
    //Private members
    private int m_uID = 0;
    private NotifyIcon notifyIcon;

    //Constructor
    public WindowSink(NotifyIcon notIcon)
    {
    notifyIcon = notIcon;
    }

    public int uID
    {
    set
    {
    m_uID = value;

    }
    }

    protected override void WndProc(ref Microsoft.WindowsCE.Forms.Message msg)
    {

    if (msg.Msg == WM_NOTIFY_TRAY)
    {
    if((int)msg.LParam == WM_LBUTTONDOWN)
    {
    if ((int)msg.WParam == m_uID)
    {
    //If somebody hooked, raise the event
    if (notifyIcon.Click != null)
    notifyIcon.Click(notifyIcon, null);

    }
    }
    }

    }
    }
    #endregion

    }
    }

    Now take the DLL created from the above code and add it to your VB.net project as a reference.
    Here is an example of using the DLL in VB.net:

    'Icon must be registered with Project>Properties
    'and MUST be 16x16

    Imports System
    Imports System.Drawing
    Imports System.Collections
    Imports System.Windows.Forms
    Imports System.Data
    Imports System.Runtime.InteropServices

    Public Class Form1
    Inherits System.Windows.Forms.Form
    Friend WithEvents MainMenu1 As System.Windows.Forms.MainMenu

    #Region " Windows Form Designer generated code "
    #End Region

    Dim WithEvents NotifyIcon As New NotifyClient.NotifyIcon

    <DllImport("coredll.dll")> _
    Private Shared Function LoadIcon(ByVal hInst As IntPtr, ByVal IconName As String) As IntPtr
    End Function

    <DllImport("coredll.dll")> _
    Private Shared Function GetModuleHandle(ByVal lpModuleName As String) As IntPtr
    End Function

    Shared Sub main()
    Application.Run(New Form1)
    End Sub

    Public Sub EHandler(ByVal sender As System.Object, ByVal e As System.EventArgs)
    MessageBox.Show("Tray Icon clicked! ")
    End Sub

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
    AddHandler NotifyIcon.Click, AddressOf EHandler
    Dim hIcon As IntPtr
    hIcon = LoadIcon(GetModuleHandle(Nothing), "#32512")
    NotifyIcon.Add(hIcon)
    End Sub
    Private Sub Form1_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
    NotifyIcon.Remove()
    End Sub
    End Class


    I still havent figured out how to register a 32x32 Icon for the windows/programs screen, and still get a handle on the 16x16 icon for the tray. My .ICO file includes both.
  • 08-28-2006 20:17 In reply to

    Re: System Tray and VB.NET

    Great Sample..!!!
    But...I've a question....how to minimize form at startup of application by code?
    When i lunch my application, the icon is added to systray and form is maximized.....If i use me.hide, me.visible = false....i've not any result....the form disappear but controlbar, menu and "X" are viewed....how to view desktop????

    Thanks !!![?]
  • 04-18-2007 4:19 In reply to

    Re: System Tray and VB.NET

    I put a Timer in and set it to 3 seconds.
    Then I put Me.Hide() in the timer Tick event and also dissabled the timer to hide the form.

    You can then show the form again on the NotigyIcon Click event.


    quote:
    Originally posted by AisMen

    Great Sample..!!!
    But...I've a question....how to minimize form at startup of application by code?
    When i lunch my application, the icon is added to systray and form is maximized.....If i use me.hide, me.visible = false....i've not any result....the form disappear but controlbar, menu and "X" are viewed....how to view desktop????

    Thanks !!![?]

  • 07-31-2007 9:27 In reply to

    Re: System Tray and VB.NET

    Wow, really a great sample!

    Anyway, one question. I use that DLL an the VB sample code have an icon in the notifcation tray thats representing the battery state (charging and battery level). That works great. So, whenever the battery state changes e. g. from charging to not charging, the app is supposed to display an appropriate icon to which I have a valid handle. Well, the "charging" icon disappears but opposed to what I expect the new icon is not being displayed at all. However, still can tap the "invisible" icon and it will still react on that click event.

    Any idea?

    I'd appreciate any hint.
  • 07-03-2009 7:56 In reply to

    • wix
    • Not Ranked
    • Joined on 07-03-2009
    • Posts 1

    Re: System Tray and VB.NET

     Hi

     

    Is it possible to get this dll ?

     

    Thank you !

     

    I got the error  "WindowSink" type undefined when I try to compile it with vs.net 2005.

     

    Thanks for your help.

Page 1 of 1 (7 items)