介绍一种在C#中实现系统拖盘处的气泡提示,提供一个Demo程序下载。点此下载
效果如图:
已把它封装成类,调用极其方便,代码如下。
using
System;
using
System.Drawing;
using
System.Windows.Forms;
using
System.Runtime.InteropServices;
using
System.ComponentModel;
using
System.Reflection;
namespace
JCMLib
{
publicclassNotifyIconEx:System.ComponentModel.Component
{
NotifyIconTargetWindow#regionNotifyIconTargetWindow
privateclassNotifyIconTarget:System.Windows.Forms.Form
{
publicNotifyIconTarget()
{
this.Text="HiddenNotifyIconTargetWindow";
}
protectedoverridevoidDefWndProc(refMessagemsg)
{
if(msg.Msg==0x400)//WM_USER
{
uintmsgId=(uint)msg.LParam;
uintid=(uint)msg.WParam;
switch(msgId)
{
case0x201://WM_LBUTTONDOWN
break;
case0x202://WM_LBUTTONUP
if(ClickNotify!=null)
ClickNotify(this,id);
break;
case0x203://WM_LBUTTONDBLCLK
if(DoubleClickNotify!=null)
DoubleClickNotify(this,id);
break;
case0x205://WM_RBUTTONUP
if(RightClickNotify!=null)
RightClickNotify(this,id);
break;
case0x200://WM_MOUSEMOVE
break;
case0x402://NIN_BALLOONSHOW
break;
//thisshouldhappenwhentheballoonisclosedusingthex
//-weneverseemtogetthismessage!
case0x403://NIN_BALLOONHIDE
break;
//weseemtogetthisnextmessagewhethertheballoontimes
//outorwhetheritisclosedusingthex
case0x404://NIN_BALLOONTIMEOUT
break;
case0x405://NIN_BALLOONUSERCLICK
if(ClickBalloonNotify!=null)
ClickBalloonNotify(this,id);
break;
}
}
elseif(msg.Msg==0xC086)//WM_TASKBAR_CREATED
{
if(TaskbarCreated!=null)
TaskbarCreated(this,System.EventArgs.Empty);
}
else
{
base.DefWndProc(refmsg);
}
}
publicdelegatevoidNotifyIconHandler(objectsender,uintid);
publiceventNotifyIconHandlerClickNotify;
publiceventNotifyIconHandlerDoubleClickNotify;
publiceventNotifyIconHandlerRightClickNotify;
publiceventNotifyIconHandlerClickBalloonNotify;
publiceventEventHandlerTaskbarCreated;
}
#endregion

PlatformInvoke#regionPlatformInvoke
[StructLayout(LayoutKind.Sequential)]privatestructNotifyIconData
{
publicSystem.UInt32cbSize;//DWORD
publicSystem.IntPtrhWnd;//HWND
publicSystem.UInt32uID;//UINT
publicNotifyFlagsuFlags;//UINT
publicSystem.UInt32uCallbackMessage;//UINT
publicSystem.IntPtrhIcon;//HICON
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=128)]
publicSystem.StringszTip;//char[128]
publicNotifyStatedwState;//DWORD
publicNotifyStatedwStateMask;//DWORD
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=256)]
publicSystem.StringszInfo;//char[256]
publicSystem.UInt32uTimeoutOrVersion;//UINT
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=64)]
publicSystem.StringszInfoTitle;//char[64]
publicNotifyInfoFlagsdwInfoFlags;//DWORD
}
[DllImport("shell32.Dll")]
privatestaticexternSystem.Int32Shell_NotifyIcon(NotifyCommandcmd,refNotifyIconDatadata);
[DllImport("User32.Dll")]
privatestaticexternSystem.Int32TrackPopupMenuEx(System.IntPtrhMenu,
System.UInt32uFlags,
System.Int32x,
System.Int32y,
System.IntPtrhWnd,
System.IntPtrignore);
[StructLayout(LayoutKind.Sequential)]privatestructPOINT
{
publicSystem.Int32x;
publicSystem.Int32y;
}
[DllImport("User32.Dll")]
privatestaticexternSystem.Int32GetCursorPos(refPOINTpoint);
[DllImport("User32.Dll")]
privatestaticexternSystem.Int32SetForegroundWindow(System.IntPtrhWnd);
#endregion

publicenumNotifyInfoFlags{Error=0x03,Info=0x01,None=0x00,Warning=0x02}
privateenumNotifyCommand{Add=0x00,Delete=0x02,Modify=0x01}
privateenumNotifyFlags{Message=0x01,Icon=0x02,Tip=0x04,Info=0x10,State=0x08}
privateenumNotifyState{Hidden=0x01}
privateuintm_id=0;//eachiconinthenotificationareahasanid
privateIntPtrm_handle;//savethehandlesothatwecanremoveicon
privatestaticNotifyIconTargetm_messageSink=newNotifyIconTarget();
privatestaticuintm_nextId=1;
privatestringm_text="";
privateIconm_icon=null;
privateContextMenum_contextMenu=null;
privateboolm_visible=false;
privateboolm_doubleClick=false;//fixforextramouseupmessagewewanttodiscard
publiceventEventHandlerClick;
publiceventEventHandlerDoubleClick;
publiceventEventHandlerBalloonClick;

Properties#regionProperties
publicstringText
{
set
{
if(m_text!=value)
{
m_text=value;
CreateOrUpdate();
}
}
get
{
returnm_text;
}
}
publicIconIcon
{
set
{
m_icon=value;
CreateOrUpdate();
}
get
{
returnm_icon;
}
}
publicContextMenuContextMenu
{
set
{
m_contextMenu=value;
}
get
{
returnm_contextMenu;
}
}
publicboolVisible
{
set
{
if(m_visible!=value)
{
m_visible=value;
CreateOrUpdate();
}
}
get
{
returnm_visible;
}
}
#endregion
publicNotifyIconEx()
{
}
//thismethodaddsthenotificationiconifithasnotbeenaddedandifwe
//haveenoughdatatodoso
privatevoidCreateOrUpdate()
{
if(this.DesignMode)
return;
if(m_id==0)
{
if(m_icon!=null)
{
//createiconusingavailableproperties
Create(m_nextId++);
}
}
else
{
//updatenotifyicon
Update();
}
}
privatevoidCreate(uintid)
{
NotifyIconDatadata=newNotifyIconData();
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;//thisshouldalwaysbevalid
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,refdata);
//addhandlers
m_messageSink.ClickNotify+=newNotifyIconTarget.NotifyIconHandler(OnClick);
m_messageSink.DoubleClickNotify+=newNotifyIconTarget.NotifyIconHandler(OnDoubleClick);
m_messageSink.RightClickNotify+=newNotifyIconTarget.NotifyIconHandler(OnRightClick);
m_messageSink.ClickBalloonNotify+=newNotifyIconTarget.NotifyIconHandler(OnClickBalloon);
m_messageSink.TaskbarCreated+=newEventHandler(OnTaskbarCreated);
}
//updateanexistingicon
privatevoidUpdate()
{
NotifyIconDatadata=newNotifyIconData();
data.cbSize=(uint)Marshal.SizeOf(data);
data.hWnd=m_messageSink.Handle;
data.uID=m_id;
data.hIcon=m_icon.Handle;//thisshouldalwaysbevalid
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,refdata);
}
protectedoverridevoidDispose(booldisposing)
{
Remove();
base.Dispose(disposing);
}
publicvoidRemove()
{
if(m_id!=0)
{
//removethenotifyicon
NotifyIconDatadata=newNotifyIconData();
data.cbSize=(uint)Marshal.SizeOf(data);
data.hWnd=m_handle;
data.uID=m_id;
Shell_NotifyIcon(NotifyCommand.Delete,refdata);
m_id=0;
}
}
publicvoidShowBalloon(stringtitle,stringtext,NotifyInfoFlagstype,inttimeoutInMilliSeconds)
{
if(timeoutInMilliSeconds<0)
thrownewArgumentException("Theparametermustbepositive","timeoutInMilliseconds");
NotifyIconDatadata=newNotifyIconData();
data.cbSize=(uint)Marshal.SizeOf(data);
data.hWnd=m_messageSink.Handle;
data.uID=m_id;
data.uFlags=NotifyFlags.Info;
data.uTimeoutOrVersion=(uint)timeoutInMilliSeconds;//thisvaluedoesnotseemtowork-anyideas?
data.szInfoTitle=title;
data.szInfo=text;
data.dwInfoFlags=type;
Shell_NotifyIcon(NotifyCommand.Modify,refdata);
}

MessageHandlers#regionMessageHandlers
privatevoidOnClick(objectsender,uintid)
{
if(id==m_id)
{
if(!m_doubleClick&&Click!=null)
Click(this,EventArgs.Empty);
m_doubleClick=false;
}
}
privatevoidOnRightClick(objectsender,uintid)
{
if(id==m_id)
{
//showcontextmenu
if(m_contextMenu!=null)
{
POINTpoint=newPOINT();
GetCursorPos(refpoint);
SetForegroundWindow(m_messageSink.Handle);//thisensuresthatifweshowthemenuandthenclickonanotherwindowthemenuwillclose
//callnonpublicmemberofContextMenu
m_contextMenu.GetType().InvokeMember("OnPopup",
BindingFlags.NonPublic|BindingFlags.InvokeMethod|BindingFlags.Instance,
null,m_contextMenu,newObject[]{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);
}
}
}
privatevoidOnDoubleClick(objectsender,uintid)
{
if(id==m_id)
{
m_doubleClick=true;
if(DoubleClick!=null)
DoubleClick(this,EventArgs.Empty);
}
}
privatevoidOnClickBalloon(objectsender,uintid)
{
if(id==m_id)
if(BalloonClick!=null)
BalloonClick(this,EventArgs.Empty);
}
privatevoidOnTaskbarCreated(objectsender,EventArgse)
{
if(m_id!=0)
Create(m_id);//keeptheidthesame
}
#endregion
}
}
本文介绍如何使用C#创建系统托盘的气泡提示,并提供了完整的代码示例及封装好的类。通过简单的调用即可实现托盘图标的状态更新与气球提示的显示。
782

被折叠的 条评论
为什么被折叠?



