WPF 基础控件之托盘
框架使用 大于等于.NET40。
Visual Studio 2022。
项目使用 MIT 开源许可协议。
新建NotifyIcon自定义控件继承自FrameworkElement。
创建托盘程序主要借助与 Win32API:
注册窗体对象RegisterClassEx。注册消息获取对应消息标识Id RegisterWindowMessage。创建窗体(本质上托盘在创建时需要一个窗口句柄,完全可以将主窗体的句柄给进去,但是为了更好的管理消息以及托盘的生命周期,通常会创建一个独立不可见的窗口)CreateWindowEx。
以下2点需要注意:
托盘控件的ContextMenu菜单MenuItem 在使用binding时无效,是因为DataContext没有带过去,需要重新赋值一次。托盘控件发送ShowBalloonTip消息通知时候需新建Shell_NotifyIcon。Nuget 最新 Install-Package WPFDevelopers 1.0.9.1-preview
示例代码
1) NotifyIcon.cs 代码如下: - usingSystem;
- usingSystem.IO;
- usingSystem.Runtime.InteropServices;
- usingSystem.Threading;
- usingSystem.Windows;
- usingSystem.Windows.Controls;
- usingSystem.Windows.ontrols.Primitives;
- usingSystem.Windows.Data;
- usingSystem.Windows.Input;
- usingSystem.Windows.Media;
- usingSystem.Windows.Media.Imaging;
- usingWPFDevelopers.Controls.Runtimes;
- usingWPFDevelopers.Controls.Runtimes.Interop;
- usingWPFDevelopers.Controls.Runtimes.Shell32;
- usingWPFDevelopers.Controls.Runtimes.User32;
- namespaceWPFDevelopers.Controls
- {
- publicclassNotifyIcon:FrameworkElement,IDisposable
- {
- privatestaticNotifyIconNotifyIconCache;
- publicstaticreadonlyDependencyPropertyContextContentProperty=DependencyProperty.Register(
- "ContextContent",typeof(object),typeof(NotifyIcon),newPropertyMetadata(default));
- publicstaticreadonlyDependencyPropertyIconProperty=
- DependencyProperty.Register("Icon",typeof(ImageSource),typeof(NotifyIcon),
- newPropertyMetadata(default,OnIconPropertyChanged));
- publicstaticreadonlyDependencyPropertyTitleProperty=
- DependencyProperty.Register("Title",typeof(string),typeof(NotifyIcon),
- newPropertyMetadata(default,OnTitlePropertyChanged));
- publicstaticreadonlyRoutedEventClickEvent=
- EventManager.RegisterRoutedEvent("Click",RoutingStrategy.Bubble,
- typeof(RoutedEventHandler),typeof(NotifyIcon));
- publicstaticreadonlyRoutedEventMouseDoubleClickEvent=
- EventManager.RegisterRoutedEvent("MouseDoubleClick",RoutingStrategy.Bubble,
- typeof(RoutedEventHandler),typeof(NotifyIcon));
- privatestaticbools_Loaded=false;
- privatestaticNotifyIcons_NotifyIcon;
- //这是窗口名称
- privatereadonlystring_TrayWndClassName;
- //这个是窗口消息名称
- privatereadonlystring_TrayWndMessage;
- //这个是窗口消息回调(窗口消息都需要在此捕获)
- privatereadonlyWndProc_TrayWndProc;
- privatePopup_contextContent;
- privatebool_doubleClick;
- //图标句柄
- privateIntPtr_hIcon=IntPtr.Zero;
- privateImageSource_icon;
- privateIntPtr_iconHandle;
- privateint_IsShowIn;
- //托盘对象
- privateNOTIFYICONDATA_NOTIFYICONDATA;
- //这个是传递给托盘的鼠标消息id
- privateint_TrayMouseMessage;
- //窗口句柄
- privateIntPtr_TrayWindowHandle=IntPtr.Zero;
- //通过注册窗口消息可以获取唯一标识Id
- privateint_WmTrayWindowMessage;
- privatebooldisposedValue;
- publicNotifyIcon()
- {
- _TrayWndClassName=$"WPFDevelopers_{Guid.NewGuid()}";
- _TrayWndProc=WndProc_CallBack;
- _TrayWndMessage="TrayWndMessageName";
- _TrayMouseMessage=(int)WM.USER+1024;
- Start();
- if(Application.Current!=null)
- {
- //Application.Current.MainWindow.Closed+=(s,e)=>Dispose();
- Application.Current.Exit+=(s,e)=>Dispose();
- }
- NotifyIconCache=this;
- }
- staticNotifyIcon()
- {
- DataContextProperty.OverrideMetadata(typeof(NotifyIcon),newFrameworkPropertyMetadata(DataContextPropertyChanged));
- ContextMenuProperty.OverrideMetadata(typeof(NotifyIcon),newFrameworkPropertyMetadata(ContextMenuPropertyChanged));
- }
- privatestaticvoidDataContextPropertyChanged(DependencyObjectd,DependencyPropertyChangedEventArgse)=>
- ((NotifyIcon)d).OnDataContextPropertyChanged(e);
- privatevoidOnDataContextPropertyChanged(DependencyPropertyChangedEventArgse)
- {
- UpdateDataContext(_contextContent,e.OldValue,e.NewValue);
- UpdateDataContext(ContextMenu,e.OldValue,e.NewValue);
- }
- privatevoidUpdateDataContext(FrameworkElementtarget,objectoldValue,objectnewValue)
- {
- if(target==null||BindingOperations.GetBindingExpression(target,DataContextProperty)!=null)return;
- if(ReferenceEquals(this,target.DataContext)||Equals(oldValue,target.DataContext))
- {
- target.DataContext=newValue??this;
- }
- }
- privatestaticvoidContextMenuPropertyChanged(DependencyObjectd,DependencyPropertyChangedEventArgse)
- {
- varctl=(NotifyIcon)d;
- ctl.OnContextMenuPropertyChanged(e);
- }
- privatevoidOnContextMenuPropertyChanged(DependencyPropertyChangedEventArgse)=>
- UpdateDataContext((ContextMenu)e.NewValue,null,DataContext);
- publicobjectContextContent
- {
- get=>GetValue(ContextContentProperty);
- set=>SetValue(ContextContentProperty,value);
- }
- publicImageSourceIcon
- {
- get=>(ImageSource)GetValue(IconProperty);
- set=>SetValue(IconProperty,value);
- }
- publicstringTitle
- {
- get=>(string)GetValue(TitleProperty);
- set=>SetValue(TitleProperty,value);
- }
- publicvoidDispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
- privatestaticvoidOnTitlePropertyChanged(DependencyObjectd,DependencyPropertyChangedEventArgse)
- {
- if(disNotifyIcontrayService)
- trayService.ChangeTitle(e.NewValue?.ToString());
- }
- privatestaticvoidOnIconPropertyChanged(DependencyObjectd,DependencyPropertyChangedEventArgse)
- {
- if(disNotifyIcontrayService)
- {
- varnotifyIcon=(NotifyIcon)d;
- notifyIcon._icon=(ImageSource)e.NewValue;
- trayService.ChangeIcon();
- }
- }
- publiceventRoutedEventHandlerClick
- {
- add=>AddHandler(ClickEvent,value);
- remove=>RemoveHandler(ClickEvent,value);
- }
- publiceventRoutedEventHandlerMouseDoubleClick
- {
- add=>AddHandler(MouseDoubleClickEvent,value);
- remove=>RemoveHandler(MouseDoubleClickEvent,value);
- }
- privatestaticvoidCurrent_Exit(objectsender,ExitEventArgse)
- {
- s_NotifyIcon?.Dispose();
- s_NotifyIcon=default;
- }
- publicboolStart()
- {
- RegisterClass(_TrayWndClassName,_TrayWndProc,_TrayWndMessage);
- LoadNotifyIconData(string.Empty);
- Show();
- returntrue;
- }
- publicboolStop()
- {
- //销毁窗体
- if(_TrayWindowHandle!=IntPtr.Zero)
- if(User32Interop.IsWindow(_TrayWindowHandle))
- User32Interop.DestroyWindow(_TrayWindowHandle);
- //反注册窗口类
- if(!string.IsNullOrWhiteSpace(_TrayWndClassName))
- User32Interop.UnregisterClassName(_TrayWndClassName,Kernel32Interop.GetModuleHandle(default));
- //销毁Icon
- if(_hIcon!=IntPtr.Zero)
- User32Interop.DestroyIcon(_hIcon);
- Hide();
- returntrue;
- }
- ///<summary>
- ///注册并创建窗口对象
- ///</summary>
- ///<paramname="className">窗口名称</param>
- ///<paramname="messageName">窗口消息名称</param>
- ///<returns></returns>
- privateboolRegisterClass(stringclassName,WndProcwndproccallback,stringmessageName)
- {
- varwndClass=newWNDCLASSEX
- {
- cbSize=Marshal.SizeOf(typeof(WNDCLASSEX)),
- style=0,
- lpfnWndProc=wndproccallback,
- cbClsExtra=0,
- cbWndExtra=0,
- hInstance=IntPtr.Zero,
- hCursor=IntPtr.Zero,
- hbrBackground=IntPtr.Zero,
- lpszMenuName=string.Empty,
- lpszClassName=className
- };
- //注册窗体对象
- User32Interop.RegisterClassEx(refwndClass);
- //注册消息获取对应消息标识id
- _WmTrayWindowMessage=User32Interop.RegisterWindowMessage(messageName);
- //创建窗体(本质上托盘在创建时需要一个窗口句柄,完全可以将主窗体的句柄给进去,但是为了更好的管理消息以及托盘的生命周期,通常会创建一个独立不可见的窗口)
- _TrayWindowHandle=User32Interop.CreateWindowEx(0,className,"",0,0,0,1,1,IntPtr.Zero,IntPtr.Zero,
- IntPtr.Zero,IntPtr.Zero);
- returntrue;
- }
- ///<summary>
- ///创建托盘对象
- ///</summary>
- ///<paramname="icon">图标路径,可以修改托盘图标(本质上是可以接受用户传入一个图片对象,然后将图片转成Icon,但是算了这个有点复杂)</param>
- ///<paramname="title">托盘的tooltip</param>
- ///<returns></returns>
- privateboolLoadNotifyIconData(stringtitle)
- {
- lock(this)
- {
- _NOTIFYICONDATA=NOTIFYICONDATA.GetDefaultNotifyData(_TrayWindowHandle);
- if(_TrayMouseMessage!=0)
- _NOTIFYICONDATA.uCallbackMessage=(uint)_TrayMouseMessage;
- else
- _TrayMouseMessage=(int)_NOTIFYICONDATA.uCallbackMessage;
- if(_iconHandle==IntPtr.Zero)
- {
- varprocessPath=Kernel32Interop.GetModuleFileName(newHandleRef());
- if(!string.IsNullOrWhiteSpace(processPath))
- {
- varindex=IntPtr.Zero;
- varhIcon=Shell32Interop.ExtractAssociatedIcon(IntPtr.Zero,processPath,refindex);
- _NOTIFYICONDATA.hIcon=hIcon;
- _hIcon=hIcon;
- }
- }
- if(!string.IsNullOrWhiteSpace(title))
- _NOTIFYICONDATA.szTip=title;
- }
- returntrue;
- }
- privateboolShow()
- {
- varcommand=NotifyCommand.NIM_Add;
- if(Thread.VolatileRead(ref_IsShowIn)==1)
- command=NotifyCommand.NIM_Modify;
- else
- Thread.VolatileWrite(ref_IsShowIn,1);
- lock(this)
- {
- returnShell32Interop.Shell_NotifyIcon(command,ref_NOTIFYICONDATA);
- }
- }
- internalstaticintAlignToBytes(doubleoriginal,intnBytesCount)
- {
- varnBitsCount=8<<(nBytesCount-1);
- return((int)Math.Ceiling(original)+(nBitsCount-1))/nBitsCount*nBitsCount;
- }
- privatestaticbyte[]GenerateMaskArray(intwidth,intheight,byte[]colorArray)
- {
- varnCount=width*height;
- varbytesPerScanLine=AlignToBytes(width,2)/8;
- varbitsMask=newbyte[bytesPerScanLine*height];
- for(vari=0;i<nCount;i++)
- {
- varhPos=i%width;
- varvPos=i/width;
- varbyteIndex=hPos/8;
- varoffsetBit=(byte)(0x80>>(hPos%8));
- if(colorArray[i*4+3]==0x00)
- bitsMask[byteIndex+bytesPerScanLine*vPos]|=offsetBit;
- else
- bitsMask[byteIndex+bytesPerScanLine*vPos]&=(byte)~offsetBit;
- if(hPos==width-1&&width==8)bitsMask[1+bytesPerScanLine*vPos]=0xff;
- }
- returnbitsMask;
- }
- privatebyte[]BitmapImageToByteArray(BitmapImagebmp)
- {
- byte[]bytearray=null;
- try
- {
- varsmarket=bmp.StreamSource;
- if(smarket!=null&&smarket.Length>0)
- {
- //设置当前位置
- smarket.Position=0;
- using(varbr=newBinaryReader(smarket))
- {
- bytearray=br.ReadBytes((int)smarket.Length);
- }
- }
- }
- catch(Exceptionex)
- {
- }
- returnbytearray;
- }
- privatebyte[]ConvertBitmapSourceToBitmapImage(
- BitmapSourcebitmapSource)
- {
- byte[]imgByte=default;
- if(!(bitmapSourceisBitmapImagebitmapImage))
- {
- bitmapImage=newBitmapImage();
- varencoder=newBmpBitmapEncoder();
- encoder.Frames.Add(BitmapFrame.Create(bitmapSource));
- using(varmemoryStream=newMemoryStream())
- {
- encoder.Save(memoryStream);
- memoryStream.Position=0;
- bitmapImage.BeginInit();
- bitmapImage.CacheOption=BitmapCacheOption.OnLoad;
- bitmapImage.StreamSource=memoryStream;
- bitmapImage.EndInit();
- imgByte=BitmapImageToByteArray(bitmapImage);
- }
- }
- returnimgByte;
- }
- internalstaticIconHandleCreateIconCursor(byte[]xor,intwidth,intheight,intxHotspot,
- intyHotspot,boolisIcon)
- {
- varbits=IntPtr.Zero;
- BitmapHandlecolorBitmap=null;
- varbi=newBITMAPINFO(width,-height,32)
- {
- bmiHeader_biCompression=0
- };
- colorBitmap=Gdi32Interop.CreateDIBSection(newHandleRef(null,IntPtr.Zero),refbi,0,refbits,null,0);
- if(colorBitmap.IsInvalid||bits==IntPtr.Zero)returnIconHandle.GetInvalidIcon();
- Marshal.Copy(xor,0,bits,xor.Length);
- varmaskArray=GenerateMaskArray(width,height,xor);
- varmaskBitmap=Gdi32Interop.CreateBitmap(width,height,1,1,maskArray);
- if(maskBitmap.IsInvalid)returnIconHandle.GetInvalidIcon();
- variconInfo=newGdi32Interop.ICONINFO
- {
- fIcon=isIcon,
- xHotspot=xHotspot,
- yHotspot=yHotspot,
- hbmMask=maskBitmap,
- hbmColor=colorBitmap
- };
- returnUser32Interop.CreateIconIndirect(iconInfo);
- }
- privateboolChangeIcon()
- {
- varbitmapFrame=_iconasBitmapFrame;
- if(bitmapFrame!=null&&bitmapFrame.Decoder!=null)
- if(bitmapFrame.DecoderisIconBitmapDecoder)
- {
- //variconBitmapDecoder=newRect(0,0,_icon.Width,_icon.Height);
- //vardv=newDrawingVisual();
- //vardc=dv.RenderOpen();
- //dc.DrawImage(_icon,iconBitmapDecoder);
- //dc.Close();
- //varbmp=newRenderTargetBitmap((int)_icon.Width,(int)_icon.Height,96,96,
- //PixelFormats.Pbgra32);
- //bmp.Render(dv);
- //BitmapSourcebitmapSource=bmp;
- //if(bitmapSource.Format!=PixelFormats.Bgra32&&bitmapSource.Format!=PixelFormats.Pbgra32)
- //bitmapSource=newFormatConvertedBitmap(bitmapSource,PixelFormats.Bgra32,null,0.0);
- varw=bitmapFrame.PixelWidth;
- varh=bitmapFrame.PixelHeight;
- varbpp=bitmapFrame.Format.BitsPerPixel;
- varstride=(bpp*w+31)/32*4;
- varsizeCopyPixels=stride*h;
- varxor=newbyte[sizeCopyPixels];
- bitmapFrame.CopyPixels(xor,stride,0);
- variconHandle=CreateIconCursor(xor,w,h,0,0,true);
- _iconHandle=iconHandle.CriticalGetHandle();
- }
- if(Thread.VolatileRead(ref_IsShowIn)!=1)
- returnfalse;
- if(_hIcon!=IntPtr.Zero)
- {
- User32Interop.DestroyIcon(_hIcon);
- _hIcon=IntPtr.Zero;
- }
- lock(this)
- {
- if(_iconHandle!=IntPtr.Zero)
- {
- varhIcon=_iconHandle;
- _NOTIFYICONDATA.hIcon=hIcon;
- _hIcon=hIcon;
- }
- else
- {
- _NOTIFYICONDATA.hIcon=IntPtr.Zero;
- }
- returnShell32Interop.Shell_NotifyIcon(NotifyCommand.NIM_Modify,ref_NOTIFYICONDATA);
- }
- }
- privateboolChangeTitle(stringtitle)
- {
- if(Thread.VolatileRead(ref_IsShowIn)!=1)
- returnfalse;
- lock(this)
- {
- _NOTIFYICONDATA.szTip=title;
- returnShell32Interop.Shell_NotifyIcon(NotifyCommand.NIM_Modify,ref_NOTIFYICONDATA);
- }
- }
- publicstaticvoidShowBalloonTip(stringtitle,stringcontent,NotifyIconInfoTypeinfoType)
- {
- if(NotifyIconCache!=null)
- NotifyIconCache.ShowBalloonTips(title,content,infoType);
- }
- publicvoidShowBalloonTips(stringtitle,stringcontent,NotifyIconInfoTypeinfoType)
- {
- if(Thread.VolatileRead(ref_IsShowIn)!=1)
- return;
- var_ShowNOTIFYICONDATA=NOTIFYICONDATA.GetDefaultNotifyData(_TrayWindowHandle);
- _ShowNOTIFYICONDATA.uFlags=NIFFlags.NIF_INFO;
- _ShowNOTIFYICONDATA.szInfoTitle=title??string.Empty;
- _ShowNOTIFYICONDATA.szInfo=content??string.Empty;
- switch(infoType)
- {
- caseNotifyIconInfoType.Info:
- _ShowNOTIFYICONDATA.dwInfoFlags=NIIFFlags.NIIF_INFO;
- break;
- caseNotifyIconInfoType.Warning:
- _ShowNOTIFYICONDATA.dwInfoFlags=NIIFFlags.NIIF_WARNING;
- break;
- caseNotifyIconInfoType.Error:
- _ShowNOTIFYICONDATA.dwInfoFlags=NIIFFlags.NIIF_ERROR;
- break;
- caseNotifyIconInfoType.None:
- _ShowNOTIFYICONDATA.dwInfoFlags=NIIFFlags.NIIF_NONE;
- break;
- }
- Shell32Interop.Shell_NotifyIcon(NotifyCommand.NIM_Modify,ref_ShowNOTIFYICONDATA);
- }
- privateboolHide()
- {
- varisShow=Thread.VolatileRead(ref_IsShowIn);
- if(isShow!=1)
- returntrue;
- Thread.VolatileWrite(ref_IsShowIn,0);
- lock(this)
- {
- returnShell32Interop.Shell_NotifyIcon(NotifyCommand.NIM_Delete,ref_NOTIFYICONDATA);
- }
- }
- privateIntPtrWndProc_CallBack(IntPtrhwnd,WMmsg,IntPtrwParam,IntPtrlParam)
- {
- //这是窗口相关的消息
- if((int)msg==_WmTrayWindowMessage)
- {
- }
- elseif((int)msg==_TrayMouseMessage)//这是托盘上鼠标相关的消息
- {
- switch((WM)(long)lParam)
- {
- caseWM.LBUTTONDOWN:
- break;
- caseWM.LBUTTONUP:
- WMMouseUp(MouseButton.Left);
- break;
- caseWM.LBUTTONDBLCLK:
- WMMouseDown(MouseButton.Left,2);
- break;
- caseWM.RBUTTONDOWN:
- break;
- caseWM.RBUTTONUP:
- OpenMenu();
- break;
- caseWM.MOUSEMOVE:
- break;
- caseWM.MOUSEWHEEL:
- break;
- }
- }
- elseif(msg==WM.COMMAND)
- {
- }
- returnUser32Interop.DefWindowProc(hwnd,msg,wParam,lParam);
- }
- privatevoidWMMouseUp(MouseButtonbutton)
- {
- if(!_doubleClick&&button==MouseButton.Left)
- RaiseEvent(newMouseButtonEventArgs(
- Mouse.PrimaryDevice,
- Environment.TickCount,button)
- {
- RoutedEvent=ClickEvent
- });
- _doubleClick=false;
- }
- privatevoidWMMouseDown(MouseButtonbutton,intclicks)
- {
- if(clicks==2)
- {
- RaiseEvent(newMouseButtonEventArgs(
- Mouse.PrimaryDevice,
- Environment.TickCount,button)
- {
- RoutedEvent=MouseDoubleClickEvent
- });
- _doubleClick=true;
- }
- }
- privatevoidOpenMenu()
- {
- if(ContextContent!=null)
- {
- _contextContent=newPopup
- {
- Placement=PlacementMode.Mouse,
- AllowsTransparency=true,
- StaysOpen=false,
- UseLayoutRounding=true,
- SnapsToDevicePixels=true
- };
- _contextContent.Child=newContentControl
- {
- Content=ContextContent
- };
- UpdateDataContext(_contextContent,null,DataContext);
- _contextContent.IsOpen=true;
- User32Interop.SetForegroundWindow(_contextContent.Child.GetHandle());
- }
- elseif(ContextMenu!=null)
- {
- if(ContextMenu.Items.Count==0)return;
- ContextMenu.InvalidateProperty(StyleProperty);
- foreach(variteminContextMenu.Items)
- if(itemisMenuItemmenuItem)
- {
- menuItem.InvalidateProperty(StyleProperty);
- }
- else
- {
- varcontainer=ContextMenu.ItemContainerGenerator.ContainerFromItem(item)asMenuItem;
- container?.InvalidateProperty(StyleProperty);
- }
- ContextMenu.Placement=PlacementMode.Mouse;
- ContextMenu.IsOpen=true;
- User32Interop.SetForegroundWindow(ContextMenu.GetHandle());
- }
- }
- protectedvirtualvoidDispose(booldisposing)
- {
- if(!disposedValue)
- {
- if(disposing)
- Stop();
- disposedValue=true;
- }
- }
- }
- publicenumNotifyIconInfoType
- {
- ///<summary>
- ///NoIcon.
- ///</summary>
- None,
- ///<summary>
- ///AInformationIcon.
- ///</summary>
- Info,
- ///<summary>
- ///AWarningIcon.
- ///</summary>
- Warning,
- ///<summary>
- ///AErrorIcon.
- ///</summary>
- Error
- }
- }
复制代码2) NotifyIconExample.xaml 代码如下:
ContextMenu 使用如下: - <wpfdev:NotifyIconTitle="WPF开发者">
- <wpfdev:NotifyIcon.ContextMenu>
- <ContextMenu>
- <MenuItemHeader="托盘消息"Click="SendMessage_Click"/>
- <MenuItemHeader="退出"Click="Quit_Click"/>
- </ContextMenu>
- </wpfdev:NotifyIcon.ContextMenu>
- </wpfdev:NotifyIcon>
复制代码ContextContent 使用如下: - <wpfdev:NotifyIconTitle="WPF开发者">
- <wpfdev:NotifyIco.ContextContent>
- <BorderCornerRadius="3"Margin="10"
- Background="{DynamicResourceBackgroundSolidColorBrush}"
- Effect="{StaticResourceNormalShadowDepth}">
- <StackPanelVerticalAlignment="Center"Margin="16">
- <RectangleWidth="100"Height="100">
- <Rectangle.Fill>
- <ImageBrushImageSource="pack://application:,,,/Logo.ico"/>
- </Rectangle.Fill>
- </Rectangle>
- <StackPanelMargin="0,16,0,0"HorizontalAlignment="Center"Orientation="Horizontal">
- <ButtonMinWidth="100"Content="关于"
- Style="{DynamicResourcePrimaryButton}"
- Command="{BindingGithubCommand}"/>
- <ButtonMargin="16,0,0,0"MinWidth="100"Content="退出"Click="Quit_Click"/>
- </StackPanel>
- </StackPanel>
- </Border>
- </wpfdev:NotifyIcon.ContextContent>
- </wpfdev:NotifyIcon>
复制代码3) NotifyIconExample.cs 代码如下:
ContextMenu 使用如下: - privatevoidQuit_Click(objectsender,RoutedEventArgse)
- {
- Application.Current.Shutdown();
- }
- privatevoidSendMessage_Click(objectsender,RoutedEventArgse)
- {
- NotifyIcon.ShowBalloonTip("Message","WelcometoWPFDevelopers.Minimal",NotifyIconInfoType.None);
- }
复制代码ContextContent 使用如下: - privatevoidQuit_Click(objectsender,RoutedEventArgse)
- {
- Application.Current.Shutdown();
- }
- privatevoidSendMessage_Click(objectsender,RoutedEventArgse)
- {
- NotifyIcon.ShowBalloonTip("Message","WelcometoWPFDevelopers.Minimal",NotifyIconInfoType.None);
- }
复制代码 实现效果
以上就是WPF实现基础控件之托盘的示例代码的详细内容,更多关于WPF托盘的资料请关注中国红客联盟其它相关文章! |