介绍一种在C#中实现系统拖盘处的气泡提示,提供一个Demo程序下载。点此下载      
 效果如图:

 已把它封装成类,调用极其方便,代码如下。
using System;
 using System.Drawing;
 using System.Windows.Forms;
 using System.Runtime.InteropServices;
 using System.ComponentModel;
 using System.Reflection;namespace JCMLib
 {  
     public class NotifyIconEx : System.ComponentModel.Component
     {  
         Notify Icon Target Window#region Notify Icon Target Window
         private class NotifyIconTarget : System.Windows.Forms.Form
         {  
             public NotifyIconTarget()
             {  
                 this.Text = "Hidden NotifyIconTarget Window";
             }            protected override void DefWndProc(ref Message msg)
             {  
                 if(msg.Msg == 0x400) // WM_USER
                 {  
                     uint msgId = (uint)msg.LParam;
                     uint id = (uint)msg.WParam;                    switch(msgId)
                     {  
                         case 0x201: // WM_LBUTTONDOWN
                             break;                        case 0x202: // WM_LBUTTONUP
                             if(ClickNotify != null)
                                 ClickNotify(this, id);
                             break;                        case 0x203: // WM_LBUTTONDBLCLK
                             if(DoubleClickNotify != null)
                                 DoubleClickNotify(this, id);
                             break;                        case 0x205: // WM_RBUTTONUP
                             if(RightClickNotify != null)
                                 RightClickNotify(this, id);
                             break;                        case 0x200: // WM_MOUSEMOVE
                             break;                        case 0x402: // NIN_BALLOONSHOW
                             break;                        // this should happen when the balloon is closed using the x
                         // - we never seem to get this message!
                         case 0x403: // NIN_BALLOONHIDE
                             break;                        // we seem to get this next message whether the balloon times
                         // out or whether it is closed using the x
                         case 0x404: // NIN_BALLOONTIMEOUT
                             break;                        case 0x405: // NIN_BALLOONUSERCLICK
                             if(ClickBalloonNotify != null)
                                 ClickBalloonNotify(this, id);
                             break;
                     }
                 }
                 else if(msg.Msg == 0xC086) // WM_TASKBAR_CREATED
                 {  
                     if(TaskbarCreated != null)
                         TaskbarCreated(this, System.EventArgs.Empty);
                 }
                 else
                 {  
                     base.DefWndProc(ref msg);
                 }
             }            public delegate void NotifyIconHandler(object sender, uint id);
         
             public event NotifyIconHandler ClickNotify;
             public event NotifyIconHandler DoubleClickNotify;
             public event NotifyIconHandler RightClickNotify;
             public event NotifyIconHandler ClickBalloonNotify;
             public event EventHandler TaskbarCreated;
         }
         #endregion        Platform Invoke#region Platform Invoke
         [StructLayout(LayoutKind.Sequential)] private struct NotifyIconData
         {  
             public System.UInt32 cbSize; // DWORD
             public System.IntPtr hWnd; // HWND
             public System.UInt32 uID; // UINT
             public NotifyFlags uFlags; // UINT
             public System.UInt32 uCallbackMessage; // UINT
             public System.IntPtr hIcon; // HICON
             [MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)]
             public System.String szTip; // char[128]
             public NotifyState dwState; // DWORD
             public NotifyState dwStateMask; // DWORD
             [MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)]
             public System.String szInfo; // char[256]
             public System.UInt32 uTimeoutOrVersion; // UINT
             [MarshalAs(UnmanagedType.ByValTStr, SizeConst=64)]
             public System.String szInfoTitle; // char[64]
             public NotifyInfoFlags dwInfoFlags; // DWORD
         }        [DllImport("shell32.Dll")]
         private static extern System.Int32 Shell_NotifyIcon(NotifyCommand cmd, ref NotifyIconData data);        [DllImport("User32.Dll")]
         private static extern System.Int32 TrackPopupMenuEx(System.IntPtr hMenu,
             System.UInt32 uFlags,
             System.Int32 x,
             System.Int32 y,
             System.IntPtr hWnd,
             System.IntPtr ignore);        [StructLayout(LayoutKind.Sequential)] private struct POINT
         {  
             public System.Int32 x;
             public System.Int32 y;
         }        [DllImport("User32.Dll")]
         private static extern System.Int32 GetCursorPos(ref POINT point);        [DllImport("User32.Dll")]
         private static extern System.Int32 SetForegroundWindow(System.IntPtr hWnd);
         #endregion        public enum NotifyInfoFlags {Error=0x03, Info=0x01, None=0x00, Warning=0x02}
         private enum NotifyCommand {Add=0x00, Delete=0x02, Modify=0x01}
         private enum NotifyFlags {Message=0x01, Icon=0x02, Tip=0x04, Info=0x10, State=0x08}
         private enum NotifyState {Hidden=0x01}        private uint m_id = 0; // each icon in the notification area has an id
         private IntPtr m_handle; // save the handle so that we can remove icon
         private static NotifyIconTarget m_messageSink = new NotifyIconTarget();
         private static uint m_nextId = 1;
         private string m_text = "";
         private Icon m_icon = null;
         private ContextMenu m_contextMenu = null;
         private bool m_visible = false;
         private bool m_doubleClick = false; // fix for extra mouse up message we want to discard        public event EventHandler Click;
         public event EventHandler DoubleClick;
         public event EventHandler BalloonClick;        Properties#region Properties
         public string Text
         {  
             set
             {  
                 if(m_text != value)
                 {  
                     m_text = value;
                     CreateOrUpdate();
                 }
             }
             get
             {  
                 return m_text;
             }
         }        public Icon Icon
         {  
             set
             {  
                 m_icon = value;
                 CreateOrUpdate();
             }
             get
             {  
                 return m_icon;
             }
         }        public ContextMenu ContextMenu
         {  
             set
             {  
                 m_contextMenu = value;
             }
             get
             {  
                 return m_contextMenu;
             }
         }        public bool Visible
         {  
             set
             {  
                 if(m_visible != value)
                 {  
                     m_visible = value;
                     CreateOrUpdate();
                 }
             }
             get
             {  
                 return m_visible;
             }
         }
         #endregion        public NotifyIconEx()
         {  
         }        // this method adds the notification icon if it has not been added and if we
         // have enough data to do so
         private void CreateOrUpdate()
         {  
             if(this.DesignMode)
                 return;            if(m_id == 0)
             {  
                 if(m_icon != null)
                 {  
                     // create icon using available properties
                     Create(m_nextId++);
                 }
             }
             else
             {  
                 // update notify icon
                 Update();
             }
         }        private void Create(uint id)
         {  
             NotifyIconData data = new NotifyIconData();
             data.cbSize = (uint)Marshal.SizeOf(data);            m_handle = m_messageSink.Handle;
             data.hWnd = m_handle;
             m_id = id;
             data.uID = m_id;            data.uCallbackMessage = 0x400;
             data.uFlags |= NotifyFlags.Message;            data.hIcon = m_icon.Handle; // this should always be valid
             data.uFlags |= NotifyFlags.Icon;            data.szTip = m_text;
             data.uFlags |= NotifyFlags.Tip;            if(!m_visible)
                 data.dwState = NotifyState.Hidden;
             data.dwStateMask |= NotifyState.Hidden;            Shell_NotifyIcon(NotifyCommand.Add, ref data);
            // add handlers
             m_messageSink.ClickNotify += new NotifyIconTarget.NotifyIconHandler(OnClick);
             m_messageSink.DoubleClickNotify += new NotifyIconTarget.NotifyIconHandler(OnDoubleClick);
             m_messageSink.RightClickNotify += new NotifyIconTarget.NotifyIconHandler(OnRightClick);
             m_messageSink.ClickBalloonNotify += new NotifyIconTarget.NotifyIconHandler(OnClickBalloon);
             m_messageSink.TaskbarCreated += new EventHandler(OnTaskbarCreated);
         }        // update an existing icon
         private void Update()
         {  
             NotifyIconData data = new NotifyIconData();
             data.cbSize = (uint)Marshal.SizeOf(data);            data.hWnd = m_messageSink.Handle;
             data.uID = m_id;            data.hIcon = m_icon.Handle; // this should always be valid
             data.uFlags |= NotifyFlags.Icon;            data.szTip = m_text;
             data.uFlags |= NotifyFlags.Tip;
             data.uFlags |= NotifyFlags.State;            if(!m_visible)
                 data.dwState = NotifyState.Hidden;
             data.dwStateMask |= NotifyState.Hidden;            Shell_NotifyIcon(NotifyCommand.Modify, ref data);
         }        protected override void Dispose(bool disposing)
         {  
             Remove();
             base.Dispose(disposing);
         }        public void Remove()
         {  
             if(m_id != 0)
             {  
                 // remove the notify icon
                 NotifyIconData data = new NotifyIconData();
                 data.cbSize = (uint)Marshal.SizeOf(data);
                     
                 data.hWnd = m_handle;
                 data.uID = m_id;                Shell_NotifyIcon(NotifyCommand.Delete, ref data);
                m_id = 0;
             }
         }        public void ShowBalloon(string title, string text, NotifyInfoFlags type, int timeoutInMilliSeconds)
         {  
             if(timeoutInMilliSeconds < 0)
                 throw new ArgumentException("The parameter must be positive", "timeoutInMilliseconds");            NotifyIconData data = new NotifyIconData();
             data.cbSize = (uint)Marshal.SizeOf(data);
                 
             data.hWnd = m_messageSink.Handle;
             data.uID = m_id;            data.uFlags = ;
             data.uTimeoutOrVersion = (uint)timeoutInMilliSeconds; // this value does not seem to work - any ideas?
             data.szInfoTitle = title;
             data.szInfo = text;
             data.dwInfoFlags = type;            Shell_NotifyIcon(NotifyCommand.Modify, ref data);
         }        Message Handlers#region Message Handlers
        private void OnClick(object sender, uint id)
         {  
             if(id == m_id)
             {  
                 if(!m_doubleClick && Click != null)
                     Click(this, EventArgs.Empty);
                 m_doubleClick = false;
             }
         }        private void OnRightClick(object sender, uint id)
         {  
             if(id == m_id)
             {  
                 // show context menu
                 if(m_contextMenu != null)
                 {                    
                     POINT point = new POINT();
                     GetCursorPos(ref point);
                     
                     SetForegroundWindow(m_messageSink.Handle); // this ensures that if we show the menu and then click on another window the menu will close                    // call non public member of ContextMenu
                     m_contextMenu.GetType().InvokeMember("OnPopup",
                         BindingFlags.NonPublic|BindingFlags.InvokeMethod|BindingFlags.Instance,
                         null, m_contextMenu, new Object[] {System.EventArgs.Empty});                    TrackPopupMenuEx(m_contextMenu.Handle, 64, point.x, point.y, m_messageSink.Handle, IntPtr.Zero);
                     
                     // PostMessage(m_messageSink.Handle, 0, IntPtr.Zero, IntPtr.Zero);
                 }
             }
         }        private void OnDoubleClick(object sender, uint id)
         {  
             if(id == m_id)
             {  
                 m_doubleClick = true;
                 if(DoubleClick != null)
                     DoubleClick(this, EventArgs.Empty);
             }
         }        private void OnClickBalloon(object sender, uint id)
         {  
             if(id == m_id)
                 if(BalloonClick != null)
                     BalloonClick(this, EventArgs.Empty);
         }        private void OnTaskbarCreated(object sender, EventArgs e)
         {  
             if(m_id != 0)
                 Create(m_id); // keep the id the same
         }
         #endregion
     }
 } 
 
                     
            
        













 
                    

 
                 
                    