WPF应用开发:如何实现任务栏通知球?附代码片段
嘿,看起来你正在用Hardcodet的WPF TaskbarIcon组件搭建托盘功能,想要实现任务栏托盘图标上的数字通知球(也就是badge标记)对吧?我来给你一步步拆解实现方案~
首先确认一下:你用的<tb:TaskbarIcon>属于Hardcodet.Wpf.TaskbarNotification这个NuGet包,如果还没安装的话,先在NuGet包管理器里搜索安装它,或者用命令行:
Install-Package Hardcodet.Wpf.TaskbarNotification
核心思路:动态生成带数字的托盘图标
Windows原生托盘图标本身不支持直接添加badge标记,所以我们需要自己绘制带数字的图标,替换原有的托盘图标。下面是具体实现步骤:
1. 编写图标生成方法
写一个C#方法,把数字叠加到你的基础图标上,生成新的可用于TaskbarIcon的ImageSource:
private ImageSource GenerateBadgeIcon(ImageSource baseIcon, int badgeNumber) { // 如果没有通知,直接返回原图标 if (badgeNumber <= 0) return baseIcon; // 将基础图标转换为BitmapSource(兼容.ico等格式) BitmapSource baseBitmap = baseIcon as BitmapSource; if (baseBitmap == null) { using (var stream = new MemoryStream()) { ((Icon)baseIcon).Save(stream); stream.Position = 0; var decoder = BitmapDecoder.Create(stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad); baseBitmap = decoder.Frames[0]; } } // 创建可绘制的画布,叠加数字和背景 var drawingVisual = new DrawingVisual(); using (var dc = drawingVisual.RenderOpen()) { // 先绘制基础图标 dc.DrawImage(baseBitmap, new Rect(0, 0, baseBitmap.PixelWidth, baseBitmap.PixelHeight)); // 计算通知球的尺寸和位置(右上角,大小为图标1/3) int badgeSize = Math.Min(baseBitmap.PixelWidth / 3, baseBitmap.PixelHeight / 3); Rect badgeRect = new Rect(baseBitmap.PixelWidth - badgeSize, 0, badgeSize, badgeSize); // 绘制红色圆形背景(带白色边框) dc.DrawEllipse(Brushes.Red, new Pen(Brushes.White, 2), new Point(badgeRect.Left + badgeSize/2, badgeRect.Top + badgeSize/2), badgeSize/2, badgeSize/2); // 绘制数字文本(加粗白色,居中) var text = new FormattedText(badgeNumber.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface("Segoe UI Bold"), badgeSize * 0.6, Brushes.White); dc.DrawText(text, new Point(badgeRect.Left + (badgeSize - text.Width)/2, badgeRect.Top + (badgeSize - text.Height)/2)); } // 渲染为BitmapSource返回 var renderTarget = new RenderTargetBitmap(baseBitmap.PixelWidth, baseBitmap.PixelHeight, baseBitmap.DpiX, baseBitmap.DpiY, PixelFormats.Pbgra32); renderTarget.Render(drawingVisual); return renderTarget; }
2. 更新托盘图标
当有新通知时,调用上面的方法,把生成的图标赋值给你的TaskbarIcon:
// 示例:假设有5条未读通知 int unreadCount = 5; var baseIcon = new BitmapImage(new Uri("../Images/icon-one.ico", UriKind.Relative)); IconeDeNotificacao.IconSource = GenerateBadgeIcon(baseIcon, unreadCount);
3. 完善上下文菜单
你的代码里上下文菜单写了一半,这里给你补一个完整的示例,包含常用的“打开应用”和“退出”选项:
<tb:TaskbarIcon x:Name="IconeDeNotificacao" IconSource="../Images/icon-one.ico" ToolTipText="ArquivarNfe" TrayLeftMouseUp="ShowWindow_Click"> <tb:TaskbarIcon.ContextMenu> <ContextMenu> <MenuItem Header="打开应用" Click="ShowWindow_Click"/> <Separator/> <MenuItem Header="退出" Click="ExitApplication_Click"/> </ContextMenu> </tb:TaskbarIcon.ContextMenu> </tb:TaskbarIcon>
对应的后台逻辑:
private void ShowWindow_Click(object sender, RoutedEventArgs e) { // 显示并激活主窗口(避免重复创建) if (Application.Current.MainWindow == null) { Application.Current.MainWindow = new MainWindow(); } Application.Current.MainWindow.Show(); Application.Current.MainWindow.Activate(); } private void ExitApplication_Click(object sender, RoutedEventArgs e) { // 清理托盘图标后退出应用 IconeDeNotificacao.Dispose(); Application.Current.Shutdown(); }
额外提示
如果你的应用是面向Windows 10+的,也可以考虑使用系统Toast通知的Badge功能(显示在任务栏的应用图标上,而非托盘图标),但托盘图标上的数字标记还是自己绘制的方式更通用,兼容更多Windows版本。
内容的提问来源于stack exchange,提问作者Marcos Brinner pikatoons
相关产品推荐
相关产品推荐

