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;
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 (
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
private NOTIFYICONDATA GetNOTIFYICONDATA(IntPtr iconHwnd, string sTip, string boxTitle, string boxText) {
NOTIFYICONDATA nData = new NOTIFYICONDATA();
nData.cbSize = System.Runtime.InteropServices.Marshal.SizeOf(nData);
nData.hwnd = formTmpHwnd;
nData.uID = uID;
nData.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP|NIF_INFO;
nData.uCallbackMessage = WM_NOTIFY_TRAY;
nData.hIcon = iconHwnd;
nData.uTimeoutAndVersion = 10 * 1000 | NOTIFYICON_VERSION;
nData.dwInfoFlags = NIIF_INFO;
nData.szTip = sTip;
nData.szInfoTitle = boxTitle;
nData.szInfo = boxText;
return nData;
}
3) Check Shell32.dll Version >= 5
private int GetShell32VersionInfo() {
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() {
...
}
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) {
mb = System.Windows.Forms.MouseButtons.Left;
}
else if((int)msg.LParam == WM_MBUTTONDOWN) {
mb = System.Windows.Forms.MouseButtons.Middle;
}
else if((int)msg.LParam == WM_RBUTTONDOWN) {
if (servicesClass.contextMenuHwnd != IntPtr.Zero) {
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(
servicesClass.contextMenuHwnd,
2,
System.Windows.Forms.Cursor.Position.X,
System.Windows.Forms.Cursor.Position.Y,
0,
servicesClass.formHwnd,
ref r
);
}
else {
mb = System.Windows.Forms.MouseButtons.Right;
}
}
if (mb != System.Windows.Forms.MouseButtons.None && servicesClass._delegateOfCallBack != null) {
servicesClass._delegateOfCallBack(mb);
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) {
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);
o1._delegateOfCallBack = new ArLi.CommonPrj.Shell_NotifyIconEx.delegateOfCallBack(GetPoc1);
}
3) version safe
if (! o1.VersionPass) {
}
reference