.NET 1.0Visual Studio .NET 2003Windows 2003.NET 1.1Windows 2000Windows XPIntermediateDevVisual StudioWindows.NETC#
Shell_NotifyIconEx with Balloon Tooltip






3.07/5 (24 votes)
Sep 12, 2003

83773

2109
Balloon Tooltip NotifyIcon with SHELL32.dll
Introduction
the .net framework nofityicon can't support Balloon Tooltip, try use this, u can:
- MS windows classical Balloon Tooltip, becase from System API, update follow System
- multi-notifyicon
- animation icon
- callback of mouseclick
- contextMenu support
- and ... talk with my tooo bad english.
ClassBody
1) Const, STRONG by version 5
#region API_Consts internal readonly int WM_NOTIFY_TRAY = 0x0400 + 2001; internal readonly int uID = 5000;
// see shellapi.h private const int NIIF_NONE = 0x00; private const int NIIF_INFO = 0x01; private const int NIIF_WARNING = 0x02; private const int NIIF_ERROR = 0x03;
private const int NIF_MESSAGE = 0x01; private const int NIF_ICON = 0x02; private const int NIF_TIP = 0x04; private const int NIF_STATE = 0x08; private const int NIF_INFO = 0x10;
private const int NIM_ADD = 0x00; private const int NIM_MODIFY = 0x01; private const int NIM_DELETE = 0x02; private const int NIM_SETFOCUS = 0x03; private const int NIM_SETVERSION = 0x04;
private const int NIS_HIDDEN = 0x01; private const int NIS_SHAREDICON = 0x02;
private const int NOTIFYICON_OLDVERSION = 0x00; private const int NOTIFYICON_VERSION = 0x03;
[DllImport("shell32.dll", EntryPoint="Shell_NotifyIcon")] private static extern bool Shell_NotifyIcon ( // o, this's master int dwMessage, ref NOTIFYICONDATA lpData );
[StructLayout(LayoutKind.Sequential)] private struct NOTIFYICONDATA { internal int cbSize; internal IntPtr hwnd; internal int uID; internal int uFlags; internal int uCallbackMessage; internal IntPtr hIcon; [MarshalAs(UnmanagedType.ByValTStr, SizeConst=0x80)] internal string szTip; internal int dwState; internal int dwStateMask; [MarshalAs(UnmanagedType.ByValTStr, SizeConst=0xFF)] internal string szInfo; internal int uTimeoutAndVersion; [MarshalAs(UnmanagedType.ByValTStr, SizeConst=0x40)] internal string szInfoTitle; internal int dwInfoFlags; } #endregion
2) Create new struct of NOTIFYICONDATA
/// <summary> /// new struct of NOTIFYICONDATA /// </summary> private NOTIFYICONDATA GetNOTIFYICONDATA(IntPtr iconHwnd, string sTip, string boxTitle, string boxText) { NOTIFYICONDATA nData = new NOTIFYICONDATA(); nData.cbSize = System.Runtime.InteropServices.Marshal.SizeOf(nData); // struct size nData.hwnd = formTmpHwnd; // WndProc form nData.uID = uID; // message WParam, for callback nData.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP|NIF_INFO; // Flags nData.uCallbackMessage = WM_NOTIFY_TRAY; // message ID, for call back nData.hIcon = iconHwnd; // icon handle, for animation icon if u need nData.uTimeoutAndVersion = 10 * 1000 | NOTIFYICON_VERSION; // "Balloon Tooltip" timeout nData.dwInfoFlags = NIIF_INFO; // info type Flag, u can try waring, error, info nData.szTip = sTip; // tooltip message nData.szInfoTitle = boxTitle; // "Balloon Tooltip" title nData.szInfo = boxText; // "Balloon Tooltip" body return nData; }3) Check Shell32.dll Version >= 5
private int GetShell32VersionInfo() { // getversion of shell32 FileInfo fi = new FileInfo(Path.Combine(System.Environment.SystemDirectory,"shell32.dll")); if (fi.Exists) { FileVersionInfo theVersion = FileVersionInfo.GetVersionInfo(fi.FullName); int i = theVersion.FileVersion.IndexOf('.'); if (i > 0) { try { return int.Parse(theVersion.FileVersion.Substring(0,i)); } catch{} } } return 0; }
4) methods
public int AddNotifyBox(IntPtr iconHwnd, string sTip, string boxTitle, string boxText) { ... }
public int DelNotifyBox() { ... }
// use this u can create "animation icon" or "Balloon Tooltip" again public int ModiNotifyBox(IntPtr iconHwnd, string sTip, string boxTitle, string boxText) { ... }
5) pop menu anywhere
[DllImport("user32.dll", EntryPoint="TrackPopupMenu")] private static extern int TrackPopupMenu ( IntPtr hMenu, int wFlags, int x, int y, int nReserved, IntPtr hwnd, ref RECT lprc );
[StructLayout(LayoutKind.Sequential)] private struct RECT { internal int Left; internal int Top; internal int Right; internal int Bottom; }
6) process message from NotifyIcon
protected override void WndProc(ref Message msg) { if (msg.Msg == servicesClass.WM_NOTIFY_TRAY) { if ((int)msg.WParam == servicesClass.uID) { System.Windows.Forms.MouseButtons mb = System.Windows.Forms.MouseButtons.None; if((int)msg.LParam == WM_LBUTTONDOWN) { // left click mb = System.Windows.Forms.MouseButtons.Left; } else if((int)msg.LParam == WM_MBUTTONDOWN) { // middle click mb = System.Windows.Forms.MouseButtons.Middle; } else if((int)msg.LParam == WM_RBUTTONDOWN) { // right click if (servicesClass.contextMenuHwnd != IntPtr.Zero) { // if connect my menu exist. RECT r = new RECT(); r.Left = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Left; r.Right = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Right; r.Top = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Top; r.Bottom = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Right;
TrackPopupMenu( //popup the menu servicesClass.contextMenuHwnd, 2, System.Windows.Forms.Cursor.Position.X, System.Windows.Forms.Cursor.Position.Y, 0, servicesClass.formHwnd, ref r ); } else { // else callback mousebuttons.right mb = System.Windows.Forms.MouseButtons.Right; } }
if (mb != System.Windows.Forms.MouseButtons.None && servicesClass._delegateOfCallBack != null) { servicesClass._delegateOfCallBack(mb); // run delegate return; } } }
base.WndProc(ref msg); }
Exemple
1) easy call
private void button3_Click(object sender, System.EventArgs e) { new ArLi.CommonPrj.Shell_NotifyIconEx().AddNotifyBox(this.Icon.Handle,this.Text,"hello","hello word!"); }
2) use contextMenu with callback
private void GetPoc1(MouseButtons mb) { //delegate of callback if (mb == MouseButtons.Left) { MessageBox.Show("icon1"); } } private ArLi.CommonPrj.Shell_NotifyIconEx o1 = new ArLi.CommonPrj.Shell_NotifyIconEx(); private void button1_Click(object sender, System.EventArgs e) { o1.AddNotifyBox(this.Icon.Handle,this.Text,"icon1","click to start,click to startclick to start\rclick to start"); o1.ConnectMyMenu(this.Handle,this.contextMenu1.Handle); // add mymenu o1._delegateOfCallBack = new ArLi.CommonPrj.Shell_NotifyIconEx.delegateOfCallBack(GetPoc1); //const callback }
3) version safe
if (! o1.VersionPass) { // if shell32.dll too old(ie 4.0 ?) //todo: use .net framework notifyicon }