Click here to Skip to main content
Click here to Skip to main content

Shell_NotifyIconEx with Balloon Tooltip

, 11 Sep 2003
Rate this:
Please Sign up or sign in to vote.
Balloon Tooltip NotifyIcon with SHELL32.dll

Sample Image - Shell_NotifyIconEx.gif

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
} 

reference

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

ArLi
Web Developer
China China
o, my lover

Comments and Discussions

 
QuestionReal Thanks and urgent need for more help Pinmemberzezeziza114-Aug-07 3:00 
GeneralJust what i was looking for PinmemberTiagoMartins30-Nov-05 4:40 
GeneralThank You very much.. Pinmemberarkypita10-Mar-05 21:44 
GeneralNOTIFYICONDATA UniCode PinsussAnonymous24-Mar-04 17:06 
QuestionHow can i use this with a Service? PinsussAnonymous12-Nov-03 2:56 
GeneralGood job ArLi ! PinmemberRouser12-Sep-03 21:04 
GeneralRe: Good job ArLi ! PinmemberArLi12-Sep-03 23:03 
GeneralRe: Good job ArLi ! PinsitebuilderUwe Keim13-Sep-03 1:51 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.141216.1 | Last Updated 12 Sep 2003
Article Copyright 2003 by ArLi
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid