NotifyIcon Balloons
Published: 8/18/2005
I answered a question about how to display a NotifyIcon balloon today on VBCity.com. The code is actually pretty simple if you don't mind messing around with Interop, here's a sample (taken from the Skystone.Shared.Win class library):
Imports System.Runtime.InteropServices
Public Const WM_USER As Long = &H400
Public Const NIF_MESSAGE As Int32 = &H1
Public Const NIF_ICON As Int32 = &H2
Public Const NIF_STATE As Int32 = &H8
Public Const NIF_INFO As Int32 = &H10
Public Const NIF_TIP As Int32 = &H4
Public Const NIM_ADD As Int32 = &H0
Public Const NIM_MODIFY As Int32 = &H1
Public Const NIM_DELETE As Int32 = &H2
Public Const NIM_SETVERSION As Int32 = &H4
Public Const NOTIFYICON_VERSION As Int32 = &H5
Public Const NIIF_ERROR As Int32 = &H3
Public Const NIIF_INFO As Int32 = &H1
Public Const NIIF_NONE As Int32 = &H0
Public Const NIM_SETFOCUS As Int32 = &H3
Public Const NIN_BALLOONSHOW As Long = (WM_USER + 2)
Public Const NIN_BALLOONHIDE As Long = (WM_USER + 3)
Public Const NIN_BALLOONTIMEOUT As Long = (WM_USER + 4)
Public Const NIN_BALLOONUSERCLICK As Long = (WM_USER + 5)
Public Enum BalloonMessageTypes
None = &H0
Info = &H1
[Error] = &H3
End Enum
<StructLayout(LayoutKind.Sequential)> _
Public Structure NOTIFYICONDATA
Public cbSize As Int32
Public hwnd As IntPtr
Public uID As Int32
Public uFlags As Int32
Public uCallbackMessage As IntPtr
Public hIcon As IntPtr
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=128)> _
Public szTip As String
Public dwState As Int32
Public dwStateMask As Int32
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=256)> _
Public szInfo As String
Public uTimeout As Int32
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=64)> _
Public szInfoTitle As String
Public dwInfoFlags As Int32
End Structure
Public Declare Auto Function Shell_NotifyIconA Lib "shell32" (ByVal dwMessage As Integer, ByRef pnid As NOTIFYICONDATA) As Integer
<Description("Displays a notification balloon associated with the specified NotifyIcon control.")> _
Public Shared Sub DisplayBalloon(ByRef NotifyIcon As System.Windows.Forms.NotifyIcon, ByVal BalloonTitle As String, _
ByVal BalloonText As String, Optional ByVal MessageType As BalloonMessageTypes = BalloonMessageTypes.None)
Dim typNotifyIcon As Type = GetType(System.Windows.Forms.NotifyIcon)
Dim ptrWindow As IntPtr = (CType(typNotifyIcon.GetField("window", System.Reflection.BindingFlags.Instance Or _
System.Reflection.BindingFlags.NonPublic).GetValue(NotifyIcon), System.Windows.Forms.NativeWindow)).Handle
Dim id As Int32 = CType(typNotifyIcon.GetField("id", System.Reflection.BindingFlags.Instance Or _
System.Reflection.BindingFlags.NonPublic).GetValue(NotifyIcon), Integer)
Dim clsNID As NOTIFYICONDATA
With clsNID
.szTip = ""
.dwState = 0
.dwStateMask = 0
.hIcon = IntPtr.Zero
.uCallbackMessage = New IntPtr(&H200)
.uID = id
.hwnd = ptrWindow
.szInfo = BalloonText
.szInfoTitle = BalloonTitle
.uFlags = NIF_INFO
.cbSize = Marshal.SizeOf(clsNID)
.dwInfoFlags = CType(MessageType, Int32)
.uTimeout = NOTIFYICON_VERSION
End With
Dim result As Int32 = Shell_NotifyIconA(NIM_MODIFY, clsNID)
End Sub
<Description("Hides any notification balloon associated with the specified NotifyIcon control.")> _
Public Shared Sub HideBalloon(ByRef NotifyIcon As System.Windows.Forms.NotifyIcon)
Dim typNotifyIcon As Type = GetType(System.Windows.Forms.NotifyIcon)
Dim ptrWindow As IntPtr = (CType(typNotifyIcon.GetField("window", System.Reflection.BindingFlags.Instance Or _
System.Reflection.BindingFlags.NonPublic).GetValue(NotifyIcon), System.Windows.Forms.NativeWindow)).Handle
Dim id As Int32 = CType(typNotifyIcon.GetField("id", System.Reflection.BindingFlags.Instance Or System.Reflection.BindingFlags.NonPublic).GetValue(NotifyIcon), Integer)
Dim clsNID As NOTIFYICONDATA
With clsNID
.szTip = ""
.dwState = 0
.dwStateMask = 0
.hIcon = IntPtr.Zero
.uCallbackMessage = New IntPtr(&H200)
.uID = id
.hwnd = ptrWindow
.szInfo = ""
.szInfoTitle = ""
.uFlags = NIF_INFO
.cbSize = Marshal.SizeOf(clsNID)
.dwInfoFlags = CType(BalloonMessageTypes.None, Int32)
.uTimeout = NOTIFYICON_VERSION
End With
Dim result As Int32 = Shell_NotifyIconA(NIM_MODIFY, clsNID)
End Sub
Once shown, your application may want to respond to user-interaction with the bubble. To do so, you can subclass the NativeWindow class, and look for the special Notify Icon messages sent to the window:
<Description("Returns a class that will raise events related to the specified NotifyIcon balloon events.")> _
Public Shared Function HookBalloonEvents(ByVal NotifyIcon As System.Windows.Forms.NotifyIcon) As NotifyIconBubble
Dim clsEvents As New NotifyIconBubble
Dim typNotifyIcon As Type = GetType(System.Windows.Forms.NotifyIcon)
Dim ptrWindow As IntPtr = (CType(typNotifyIcon.GetField("window", System.Reflection.BindingFlags.Instance _
Or System.Reflection.BindingFlags.NonPublic).GetValue(NotifyIcon), System.Windows.Forms.NativeWindow)).Handle
clsEvents.AssignHandle(ptrWindow)
Return clsEvents
End Function
<Description("Defines a class that will raise events related to the specified NotifyIcon balloon events.")> _
Public Class NotifyIconBubble
Inherits System.Windows.Forms.NativeWindow
Public Event BallonHidden()
Public Event BallonShown()
Public Event BallonTimedOut()
Public Event BallonClicked()
Friend Sub New()
'
End Sub
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
Select Case m.LParam.ToInt32
Case NIN_BALLOONHIDE
RaiseEvent BallonHidden()
Case NIN_BALLOONSHOW
RaiseEvent BallonShown()
Case NIN_BALLOONTIMEOUT
RaiseEvent BallonTimedOut()
Case NIN_BALLOONUSERCLICK
RaiseEvent BallonClicked()
Case Else
End Select
MyBase.WndProc(m)
End Sub
End Class
NOTE: This post has been elaborated on and turned into a FAQ on VBCity.com.
Written by Scott Waletzko for Skystone Software.
Copyright 2005-2007 by Echosoft Design Studios, LLC, All Rights Reserved.