C# Winform消息通知之系统本地通知local toast notification
作者:代码迷途 发布时间:2023-02-01 04:14:02
引言
C#应用通过 Microsoft.Toolkit.Uwp.Notifications
NuGet包可以很方便的发送本地通知(Windows 10或Windows 11 的 Toast 通知,之前系统版本未提供此类通知),适用于所有类型的应用(WPF、UWP、WinForms、控制台【实际使用各自有着不同限制】)。
后面会介绍使用任务托盘显示系统通知,从而不用使用Nuget包。
toast 通知的结构
Toast 内容的核心组件有
launch:定义当用户单击你的 Toast 时将传回应用的参数,允许深层链接到 Toast 所显示的正确内容。
visual:toast 的可视部分,包括带有文本和图像的通用绑定。
actions:toast 的交互部分,包括输入和操作。
audio:控制向用户显示 Toast 时播放的音频。
Toast 内容的可视化表示形式:
Toast 内容介绍对toast各种应用场景进行了介绍,包括文本、文本行数、图片、徽章、时间戳、进度条、按钮、输入、音频等。
发送本地toast通知的操作步骤
新建项目NotificationLocalToast
。
安装NuGet包Microsoft.Toolkit.Uwp.Notifications
推荐 7.0 及以上版本。
如果.NET Framework的桌面应用仍使用 packages.config
管理包,需要将其迁移到PackageReference
,否则不会正确引用Windows SDK。
迁移方法是:在项目中,右键单击“引用”,然后单击“将 packages.config 迁移到 PackageReference”。需要Visual Studio 2017 15.7 及更高版本才支持。
具体参见从 packages.config 迁移到 PackageReference
注:迁移到PackageReference后,需要重启VS打开项目,否则无法正确的using引用到包库。
通知的发送(文本通知)
new ToastContentBuilder()
.AddText("CodeMissing发来一条消息") // 标题文本
.AddText("请检查消息内容,并及时处理")
.Show(); // 7.0以上才提供Show方法
点击运行并发送消息,将在屏幕右下角看到toast通知
多次发送消息,会依照顺序各自依次显示(等待上一个进入操作中心或被关闭)。
处理点击通知的操作
当用户点击通知后,则会在后台线程调用ToastNotificationManagerCompat.OnActivated
事件,在程序的该事件中处理交互操作。
如果应用程序关闭,将会启动exe应用(并且 ToastNotificationManagerCompat.WasCurrentProcessToastActivated()
返回true,表示重新启动了进程),然后再在后台线程上调用 ToastNotificationManagerCompat.OnActivated 事件。
在主窗体的构造函数中处理该事件(如果不需要执行UI线程的操作,直接在Program.cs的Main函数入口处添加此监听事件即可)
public MainForm()
{
InitializeComponent();
// 监听通知激活(点击)
ToastNotificationManagerCompat.OnActivated += toastArgs =>
{
// 通知参数
ToastArguments args = ToastArguments.Parse(toastArgs.Argument);
// 获取任何用户输入
ValueSet userInput = toastArgs.UserInput;
BeginInvoke(new Action( delegate
{
// TODO: UI线程的操作
MessageBox.Show("Toast被激活(点击),参数是: " + toastArgs.Argument);
}));
};
}
当点击通知后,会显示对话框。
WPF中的(在入口程序中的)异步UI调用要通过Application.Current.Dispatcher.Invoke
,它是位于System.Windows下的Application。需要添加引用PresentationFramework
// Need to dispatch to UI thread if performing UI operations
Application.Current.Dispatcher.Invoke(delegate
{
// TODO: Show the corresponding content
MessageBox.Show("Toast activated. Args: " + toastArgs.Argument);
});
通知的卸载
如果应用有卸载程序,应该在卸载过程中调用ToastNotificationManagerCompat.Uninstall();
。
如果应用是不安装的“可移植应用”,则可根据需要在退出时调用(除非想要在退出后仍然保留通知)。
ToastNotificationManagerCompat.Uninstall()
在执行后,会将通知面板中相关的信息清理掉。
卸载方法将清理任何计划通知和当前通知,删除任何关联的注册表值,并删除库创建的任何关联的临时文件。
设置通知的过期时间
忽略的toast通知会转到操作中心(通知中心),后续仍可以查看。
但是,通常消息都有一定的期限,过期后则不应该继续显示或保留,本地 toast 通知的默认和最长过期时间为 3 天。
下面设置过期时间为2天:
new ToastContentBuilder()
.Show(toast =>
{
toast.ExpirationTime = DateTime.Now.AddDays(2);
});
.NET应用使用Toast Notifications(.NET5+)
.NET中如果使用Microsoft.Toolkit.Uwp.Notifications,必须指定Windows TFM,且要指定window版本,至少为net6.0-windows10.0.17763.0
或更高。否则,将报错找不到Show()
方法。
指定Windows TFM
右键项目,编辑项目文件,将TargetFramework
指定为如下:
<TargetFramework>net6.0-windows10.0.17763.0</TargetFramework>
通常,指定TFM后,启动调试会报错没有xxx的目标,确保已运行还原...等错误。
解决办法是:清理项目,并重新生成一次即可。
有时候还会报错net6.0-windows10.0.17763.0
与.Net
框架版本不一致,需要修改为net5.0-windows10.0.17763.0
。或者改为net5后生成无错再改回net6;或者直接清理项目并重新生成一次。
添加图像
使用http图像
目前仅仅具有Internet功能的UWP/MSIX/sparse应用才支持http的图像【sparse,松散或稀疏应用】。
UWP/MSIX开发在Package.appxmanifest
文件中用于指定Internet的能力(默认已经开启)
其他应用,比如Winform、WPF等必须将图像下载到本地,通过本地路径引用。
并且web图片引用有200KB的限制,具体参见官方文档介绍。不过有个不太清楚的地方:app's package
是什么?又如何从其中获取图片?
Images can be used from the app's package, the app's local storage, or from the web. As of the Fall Creators Update, web images can be up to 3 MB on normal connections and 1 MB on metered connections. On devices not yet running the Fall Creators Update, web images must be no larger than 200 KB.
尝试通过资源pack的方式获取图片,未成功,比如WPF图片中可以使用的"pack://application:,,,/Resources/CSharp.png"
。
内联图像和主图
下载图片到本地,并添加到项目中,设置图片属性:复制到输出目录“总是”或“较新复制”、生成操作“无”,确保图片生成到exe程序路径。
首先获取img文件的完整路径,并创建Uri,通过AddInlineImage
、AddHeroImage
添加为内联图像和主图。
使用
file:///
构建uri
var imgFileFullPath = Path.GetFullPath("Resources/CSharp.png");
var fileUriString = $"file:///{imgFileFullPath}";
var imgUri = new Uri(fileUriString);
new ToastContentBuilder()
.AddArgument("action", "viewConversation") // 添加相关参数
.AddArgument("conversationId", 9813)
.AddText("CodeMissing发来一张图片") // 标题文本
.AddText("这是C#的图片")
.AddInlineImage(imgUri) // 内联
.AddHeroImage(imgUri) // 主图
.Show();
注意本地文件的Uri访问协议:"file:///FileFullPath"
直接使用文件路径创建Uri
new Uri(localImgPath)
也可以创建uri。
var imgFileFullPath = Path.GetFullPath("Resources/CSharp.png");
new ToastContentBuilder()
.AddText("这是C#的图片")
.AddAppLogoOverride(new Uri(imgFileFullPath), ToastGenericAppLogoCrop.Circle)
.Show();
徽标和剪裁(圆形图片)
new ToastContentBuilder()
// ....
.AddAppLogoOverride(imgUri, ToastGenericAppLogoCrop.Circle)
.Show();
UWP使用http图片
new ToastContentBuilder()
.AddArgument("action", "viewConversation") // 添加相关参数
.AddArgument("conversationId", 9813)
.AddText("CodeMissing发来一张图片") // 标题文本
.AddText("这是C#的图片")
.AddInlineImage(new Uri("https://www.vippng.com/png/detail/398-3984434_c-programming-png.png"))
.AddAppLogoOverride(new Uri("https://www.vippng.com/png/detail/398-3984434_c-programming-png.png"), ToastGenericAppLogoCrop.Circle)
.Show();
图片来源于网络
替换或删除指定通知
替换或移除toast通知需要使用Tag属性(以及Group属性),两者构成toast的主键。
为 toast 设置主键
new ToastContentBuilder()
.AddText("我是含有Tag和Group的消息")
.Show(toast =>
{
toast.Tag = "codemissing101";
toast.Group = "codemissing";
});
根据Tag和Group删除或替换toast
通过使用相同的Tag和Group再次发送消息,即可以实现替换。
new ToastContentBuilder()
.AddText("我是替换的消息")
.Show(toast =>
{
toast.Tag = "codemissing101";
toast.Group = "codemissing";
});
History.Remove
或者 RemoveGroup
实现移除
ToastNotificationManagerCompat.History.Remove("codemissing101", "codemissing");
如果只有Tag则只指定Tag,如果Tag和Group都存在,则两者都需要指定才能匹配。
清除通知
ToastNotificationManagerCompat.History.Clear();
参考
从 C# 应用发送本地 toast 通知
来源:https://juejin.cn/post/7134718468716396581
猜你喜欢
- 项目中用到用户定义运算公式进行就算的需求,这样需要进行字符串四则运算解析,下面提供字符串公式四则运算解析与计算工具类,需要的同学可参考。工具
- 一、Java把这些不同来源和目标的数据都统一抽象为数据流。Java语言的输入输出功能是十分强大而灵活的。在Java类库中,IO部分的内容是很
- 1.概述在实际开发过程中,我们经常需要调用对方提供的接口或测试自己写的接口是否合适。很多项目都会封装规定好本身项目的接口规范,所以大多数需要
- 前言现在是移动端产品疯狂的年代,随之,移动端支付也是热门小技能,最近本公司在做一个移动端,要接入微信支付和支付宝支付, * 惯,功能做完之后做
- 一、实验题目二、分析实验要求为:实现一个界面,界面中包含一个文本显示区和两个按钮(存档和读档)读档按钮作用是打开文件并读取内容,将内容显示在
- 一般查询手机归属地内容应该很好用json格式保存,在网上找到了淘宝的归属地API,并下了处理json相关的jar包,做了这个手机归属地查询功
- 最近我在考虑如何远程控制tomcat的启动和关机,最后是有友好的界面,能够实现一键式操作的,这样会肯定是会很方便的,网上找了半天,没找到,有
- 文件分割与合并是一个常见需求,比如:上传大文件时,可以先分割成小块,传到服务器后,再进行合并。很多高大上的分布式文件系统(比如:google
- 现在很多流行的框架,都可以很快的把分页效果做出来,但是作为一名程序员你必须得知道手写分页的流程:场景效果:一、分页的思路首先我们得知道写分页
- 我就废话不多说了,大家还是直接看代码吧~/** * feign调用客户端 */@FeignClient(name = "user&
- 本人一直使用的是Eclipse作为开发工具的,不过现在IDEA非常的受推崇,所以决定上手试一试。网上有很多旗舰版的文章,我没有仔细看,我这次
- 一、环境说明集群环境至少需要3个节点(也就是3台服务器设备):1个Master,2个Slave,节点之间局域网连接,可以相互ping通,下面
- 注册中心呢 就是springcloud的一个核心组件 所有微服务的基石 微服务的核心思想就是分布式 所有的服务分开管理 但这些服务分开后该如
- 前言LocalDateTime、LocalDate、LocalTime 是 Java8 全新的日期框架,加强了对时间的管理,有很多特别好用的
- 我们在java中处理字符串的时候,一般会选择String,在python中同样也是作用于字符串。那么我们今天延伸一下它的用法,只使用Stri
- 1.返回String“长度”方法你如何确定给定String的长度?java提供了一种称为“length()”的方法。将它用于您需要查找Str
- 在spring中有很多以XXXAware命名的接口,很多人也不清楚这些接口都是做什么用的,这篇文章将描述常用的一些接口。一,Applicat
- @RequestBody出现400 Bad Request的问题今天与同事调试一个接口,发现后台使用@RequestBody老是获取不到数据
- 井字棋游戏要求在3乘3棋盘上,每行都相同或者每列都相同再或者对角线相同,则胜出.因此我们可以使用一个二维数组来表示棋盘,判断胜负只需要判断数
- java修改JFrame默认字体修改默认字体的方法很简单。首先我们随便写一个按钮出来:import javax.swing.*; publi