在C#中实现系统拖盘处的气泡提示

本文介绍如何使用C#创建系统托盘的气泡提示,并提供了完整的代码示例及封装好的类。通过简单的调用即可实现托盘图标的状态更新与气球提示的显示。

介绍一种在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

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值