如何在 C# Windows 应用程序中使用自定义图像和 onclick 函数发出通知?
How can I make a notification in a C# Windows app with a custom image and onclick function?
我的最终目标是在 C#.NET 中创建一个 Windows 10 应用程序,向用户显示通知。通知应该有标题、描述、至少一张图片,点击后会打开一个网页。如果用户没有点击它,它也应该存储在通知管理器中(或者 Windows 中列出通知的任何地方)。这就是目标。
我已经尝试了很多不同的方法来做到这一点,但无法使任何一种方法正常工作。
我当前的代码使用 Microsoft.Toolkit.Uwp.Notifications
NuGet 包,主要取自此示例:
https://docs.microsoft.com/en-us/windows/uwp/design/shell/tiles-and-notifications/adaptive-interactive-toasts?tabs=builder-syntax
就目前而言,以下代码运行良好:
using System;
using System.Windows;
using Microsoft.Toolkit.Uwp.Notifications;
namespace PushClient
{
public partial class App : System.Windows.Application
{
private void Application_Startup(object sender, StartupEventArgs e)
{
new ToastContentBuilder()
.AddText("My Title")
.AddText("My Description")
.Show();
}
}
}
这是它产生的通知...
第一个问题
第一个问题是我无法添加自定义图像,尽管据说可以通过三种不同的方法添加图像。我第一次尝试这个:
new ToastContentBuilder()
.AddText("My Title")
.AddText("My Description")
.AddAppLogoOverride((new Uri("https://picsum.photos/48?image=883")), ToastGenericAppLogoCrop.Circle)
.Show();
成功去除通知左侧的默认图标,并在底部添加应用的名称(因为想法是徽标已被删除,所以应用必须通过一些来识别其他方法)。然而,没有新的图像代替旧的。只是空白 space.
我也试过这个:
new ToastContentBuilder()
.AddText("My Title")
.AddText("My Description")
.AddHeroImage(new Uri("https://picsum.photos/364/180?image=1043"))
.Show();
但据我所知,这与第一个版本几乎没有任何变化。
最后我尝试了这个:
new ToastContentBuilder()
.AddText("My Title")
.AddText("My Description")
.AddInlineImage(new Uri("https://picsum.photos/360/202?image=1043"))
.Show();
这似乎在描述下方添加了一些空白 space,但没有图像。
第二个问题
另一个问题是我不知道如何通过这个过程添加一个完整的 onclick 动作。我对需要单击的按钮或通知本身的单击操作都非常满意。但不管怎么用,最终还是需要在用户的默认浏览器中打开一个指定的URL。
其他尝试
我还玩过其他发送通知的进程,比如 ShowBalloonTip
进程。对于自定义图像,这似乎根本没有选项,这正是我想要的。但是,我可以 select 指定图像列表中的图像,包括我在此代码中选择的“警告”图标,并且添加 onclick 操作很简单:
using System;
using System.Threading;
using System.Windows;
using System.Windows.Forms;
namespace PushClient
{
public partial class App : System.Windows.Application
{
private NotifyIcon _notifyIcon = new NotifyIcon();
private void Application_Startup(object sender, StartupEventArgs e)
{
try
{
_notifyIcon = new NotifyIcon();
_notifyIcon.Icon = PushClient.Properties.Resources.accountable2you;
_notifyIcon.Visible = true;
_notifyIcon.ContextMenuStrip = new System.Windows.Forms.ContextMenuStrip();
Thread t = new Thread(() => LaunchBalloonNotification(_notifyIcon, "My Title", "My Description"));
t.Start();
}
catch (System.Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
private static void notifyIcon_BalloonTipClicked(object sender, EventArgs e)
{
Console.WriteLine("Action clicked");
}
private static void LaunchBalloonNotification(NotifyIcon ico, String title, String msg)
{
ico.ShowBalloonTip(
10000,
title,
msg,
ToolTipIcon.Warning
);
ico.BalloonTipClicked += new EventHandler(notifyIcon_BalloonTipClicked);
}
}
}
我也尝试过使用 ToastNotificationManager
,但我得到的结果与我使用 Microsoft.Toolkit.Uwp.Notifications
得到的结果相同......除了 ToastNotificationManager
需要 AppID
工作,我很难弄清楚我应该如何为我的小 Visual Studio 测试应用程序创建这样的东西。
无论如何,如果你能指出正确的方向来帮助我实现我的目标(最好是 minimal, reproducible example!),我将不胜感激!
在评论中提供的 link @Fildor 的帮助下,以及对如何处理本地图像的一些创造性思考,我终于有了一个可行的解决方案。这是 link:
https://docs.microsoft.com/en-us/windows/uwp/design/shell/tiles-and-notifications/send-local-toast?tabs=desktop
我最终将我需要的两个图像(都将与应用程序一起部署)转换为数据 URI,就像人们在 HTML 中可能使用的那样。然后我将它们保存在本地。然后我在 AddAppLogoOverride
方法中使用 C# Uri
对象。可能有更简单的方法,但这是我能想到的最好的方法。
我修改后的工作(即 - 如果您使用上传到 opinionatedgeek 编码器的真实图像中的真实图像数据,则为“工作”)示例代码如下。
using System;
using System.Windows;
using Microsoft.Toolkit.Uwp.Notifications;
using System.IO;
namespace PushClient
{
public partial class App : System.Windows.Application
{
private String imageFilePath = String.Empty;
private void Application_Startup(object sender, StartupEventArgs e)
{
try
{
SaveImageFilesToCommonFolder();
LaunchToastNotification("Hello World!", "This is such a nice world!", "https://presuppositions.org");
}
catch (System.Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
private void LaunchToastNotification(string title, string description, string url)
{
// https://docs.microsoft.com/en-us/windows/uwp/design/shell/tiles-and-notifications/send-local-toast?tabs=desktop
Uri img = new Uri(imageFilePath);
// Listen to notification activation
ToastNotificationManagerCompat.OnActivated += toastArgs =>
{
// Obtain the arguments from the notification
ToastArguments args = ToastArguments.Parse(toastArgs.Argument);
//
System.Diagnostics.Process.Start(args["url"]);
};
new ToastContentBuilder()
.AddText(title)
.AddText(description)
.AddAppLogoOverride(img)
.AddButton(new ToastButton()
.SetContent("View Report")
.AddArgument("action", "viewReport")
.AddArgument("url", url))
.Show();
}
private string SaveDataUrlToFile(string dataUrl, string savePath)
{
//
var binData = Convert.FromBase64String(dataUrl);
System.IO.File.WriteAllBytes(savePath, binData);
return savePath;
}
private void SaveImageFilesToCommonFolder()
{
//
// Write images to common app data folder
var directory = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
// Uploaded PNG to this location to get the Data URI,
// which is really much longer than displayed here:
// https://www.opinionatedgeek.com/codecs/base64encoder
String imageFileData = "iVBORw0KGgoAAAANUgAAAMAAAADRU5ErkJggg==";
imageFilePath = Path.Combine(directory, "myimage.png");
SaveDataUrlToFile(imageFileData, imageFilePath);
}
}
}
如果您不需要从网络上获取图像,而只需在您的项目中引用文件,文档就不够清楚,但是当您使用常规 desktop/console 应用程序时您不受与 UWP 应用相同的限制。
您可以将文件:/// URL 直接用于您项目中的图像,它适用于应用程序图标和“英雄图像”:
var iconUri = "file:///" + Path.GetFullPath("images/icon.png");
var imageUri = "file:///" + Path.GetFullPath("images/image.jpg");
new ToastContentBuilder()
.AddText("Notification text")
.AddAppLogoOverride(new Uri(iconUri), ToastGenericAppLogoCrop.Circle)
.AddHeroImage(new Uri(imageUri))
.Show();
我达到这个 post 因为我遇到了完全相同的问题。
这很有趣,因为根据您的应用程序名称,我认为我们正在构建相同的应用程序 :)
无论如何,我找到了一种更简单的方法来实现这一目标。
首先,在您的项目上创建一个目录并将图像放在那里。就我而言,我创建了一个“图像”目录:
确保图像文件的“Build Action”设置为“Content”并且您的“”复制到输出目录”设置为“如果较新则复制”(或“始终”)。
那么你的代码可以是这样的:
var imageUri = Path.GetFullPath(@"Images\logo.png");
new ToastContentBuilder()
.AddArgument("action", "viewConversation")
.AddArgument("conversationId", 9813)
.AddText(title)
.AddText(message + " URL:" + url)
.AddAppLogoOverride(new Uri(imageUri))
.AddHeroImage(new Uri(imageUri))
.AddButton(new ToastButton()
.SetContent("Open URL")
.SetProtocolActivation(new Uri(url))
)
.Show();
结果:
可能有点晚了,但我对吐司有同样的问题,如果用户关闭了通知,不确定它是否有帮助。
为了表达祝酒词,我试了一下成功了:Tulpep.NotificationWindow
效果很好,您添加一个控件并访问所有参数,并且能够显示图像(并调整大小)。
下面是 link 的示例:https://www.c-sharpcorner.com/article/working-with-popup-notification-in-windows-forms/
我的最终目标是在 C#.NET 中创建一个 Windows 10 应用程序,向用户显示通知。通知应该有标题、描述、至少一张图片,点击后会打开一个网页。如果用户没有点击它,它也应该存储在通知管理器中(或者 Windows 中列出通知的任何地方)。这就是目标。
我已经尝试了很多不同的方法来做到这一点,但无法使任何一种方法正常工作。
我当前的代码使用 Microsoft.Toolkit.Uwp.Notifications
NuGet 包,主要取自此示例:
https://docs.microsoft.com/en-us/windows/uwp/design/shell/tiles-and-notifications/adaptive-interactive-toasts?tabs=builder-syntax
就目前而言,以下代码运行良好:
using System;
using System.Windows;
using Microsoft.Toolkit.Uwp.Notifications;
namespace PushClient
{
public partial class App : System.Windows.Application
{
private void Application_Startup(object sender, StartupEventArgs e)
{
new ToastContentBuilder()
.AddText("My Title")
.AddText("My Description")
.Show();
}
}
}
这是它产生的通知...
第一个问题
第一个问题是我无法添加自定义图像,尽管据说可以通过三种不同的方法添加图像。我第一次尝试这个:
new ToastContentBuilder()
.AddText("My Title")
.AddText("My Description")
.AddAppLogoOverride((new Uri("https://picsum.photos/48?image=883")), ToastGenericAppLogoCrop.Circle)
.Show();
成功去除通知左侧的默认图标,并在底部添加应用的名称(因为想法是徽标已被删除,所以应用必须通过一些来识别其他方法)。然而,没有新的图像代替旧的。只是空白 space.
我也试过这个:
new ToastContentBuilder()
.AddText("My Title")
.AddText("My Description")
.AddHeroImage(new Uri("https://picsum.photos/364/180?image=1043"))
.Show();
但据我所知,这与第一个版本几乎没有任何变化。
最后我尝试了这个:
new ToastContentBuilder()
.AddText("My Title")
.AddText("My Description")
.AddInlineImage(new Uri("https://picsum.photos/360/202?image=1043"))
.Show();
这似乎在描述下方添加了一些空白 space,但没有图像。
第二个问题
另一个问题是我不知道如何通过这个过程添加一个完整的 onclick 动作。我对需要单击的按钮或通知本身的单击操作都非常满意。但不管怎么用,最终还是需要在用户的默认浏览器中打开一个指定的URL。
其他尝试
我还玩过其他发送通知的进程,比如 ShowBalloonTip
进程。对于自定义图像,这似乎根本没有选项,这正是我想要的。但是,我可以 select 指定图像列表中的图像,包括我在此代码中选择的“警告”图标,并且添加 onclick 操作很简单:
using System;
using System.Threading;
using System.Windows;
using System.Windows.Forms;
namespace PushClient
{
public partial class App : System.Windows.Application
{
private NotifyIcon _notifyIcon = new NotifyIcon();
private void Application_Startup(object sender, StartupEventArgs e)
{
try
{
_notifyIcon = new NotifyIcon();
_notifyIcon.Icon = PushClient.Properties.Resources.accountable2you;
_notifyIcon.Visible = true;
_notifyIcon.ContextMenuStrip = new System.Windows.Forms.ContextMenuStrip();
Thread t = new Thread(() => LaunchBalloonNotification(_notifyIcon, "My Title", "My Description"));
t.Start();
}
catch (System.Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
private static void notifyIcon_BalloonTipClicked(object sender, EventArgs e)
{
Console.WriteLine("Action clicked");
}
private static void LaunchBalloonNotification(NotifyIcon ico, String title, String msg)
{
ico.ShowBalloonTip(
10000,
title,
msg,
ToolTipIcon.Warning
);
ico.BalloonTipClicked += new EventHandler(notifyIcon_BalloonTipClicked);
}
}
}
我也尝试过使用 ToastNotificationManager
,但我得到的结果与我使用 Microsoft.Toolkit.Uwp.Notifications
得到的结果相同......除了 ToastNotificationManager
需要 AppID
工作,我很难弄清楚我应该如何为我的小 Visual Studio 测试应用程序创建这样的东西。
无论如何,如果你能指出正确的方向来帮助我实现我的目标(最好是 minimal, reproducible example!),我将不胜感激!
在评论中提供的 link @Fildor 的帮助下,以及对如何处理本地图像的一些创造性思考,我终于有了一个可行的解决方案。这是 link: https://docs.microsoft.com/en-us/windows/uwp/design/shell/tiles-and-notifications/send-local-toast?tabs=desktop
我最终将我需要的两个图像(都将与应用程序一起部署)转换为数据 URI,就像人们在 HTML 中可能使用的那样。然后我将它们保存在本地。然后我在 AddAppLogoOverride
方法中使用 C# Uri
对象。可能有更简单的方法,但这是我能想到的最好的方法。
我修改后的工作(即 - 如果您使用上传到 opinionatedgeek 编码器的真实图像中的真实图像数据,则为“工作”)示例代码如下。
using System;
using System.Windows;
using Microsoft.Toolkit.Uwp.Notifications;
using System.IO;
namespace PushClient
{
public partial class App : System.Windows.Application
{
private String imageFilePath = String.Empty;
private void Application_Startup(object sender, StartupEventArgs e)
{
try
{
SaveImageFilesToCommonFolder();
LaunchToastNotification("Hello World!", "This is such a nice world!", "https://presuppositions.org");
}
catch (System.Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
private void LaunchToastNotification(string title, string description, string url)
{
// https://docs.microsoft.com/en-us/windows/uwp/design/shell/tiles-and-notifications/send-local-toast?tabs=desktop
Uri img = new Uri(imageFilePath);
// Listen to notification activation
ToastNotificationManagerCompat.OnActivated += toastArgs =>
{
// Obtain the arguments from the notification
ToastArguments args = ToastArguments.Parse(toastArgs.Argument);
//
System.Diagnostics.Process.Start(args["url"]);
};
new ToastContentBuilder()
.AddText(title)
.AddText(description)
.AddAppLogoOverride(img)
.AddButton(new ToastButton()
.SetContent("View Report")
.AddArgument("action", "viewReport")
.AddArgument("url", url))
.Show();
}
private string SaveDataUrlToFile(string dataUrl, string savePath)
{
//
var binData = Convert.FromBase64String(dataUrl);
System.IO.File.WriteAllBytes(savePath, binData);
return savePath;
}
private void SaveImageFilesToCommonFolder()
{
//
// Write images to common app data folder
var directory = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
// Uploaded PNG to this location to get the Data URI,
// which is really much longer than displayed here:
// https://www.opinionatedgeek.com/codecs/base64encoder
String imageFileData = "iVBORw0KGgoAAAANUgAAAMAAAADRU5ErkJggg==";
imageFilePath = Path.Combine(directory, "myimage.png");
SaveDataUrlToFile(imageFileData, imageFilePath);
}
}
}
如果您不需要从网络上获取图像,而只需在您的项目中引用文件,文档就不够清楚,但是当您使用常规 desktop/console 应用程序时您不受与 UWP 应用相同的限制。
您可以将文件:/// URL 直接用于您项目中的图像,它适用于应用程序图标和“英雄图像”:
var iconUri = "file:///" + Path.GetFullPath("images/icon.png");
var imageUri = "file:///" + Path.GetFullPath("images/image.jpg");
new ToastContentBuilder()
.AddText("Notification text")
.AddAppLogoOverride(new Uri(iconUri), ToastGenericAppLogoCrop.Circle)
.AddHeroImage(new Uri(imageUri))
.Show();
我达到这个 post 因为我遇到了完全相同的问题。 这很有趣,因为根据您的应用程序名称,我认为我们正在构建相同的应用程序 :) 无论如何,我找到了一种更简单的方法来实现这一目标。
首先,在您的项目上创建一个目录并将图像放在那里。就我而言,我创建了一个“图像”目录:
确保图像文件的“Build Action”设置为“Content”并且您的“”复制到输出目录”设置为“如果较新则复制”(或“始终”)。
那么你的代码可以是这样的:
var imageUri = Path.GetFullPath(@"Images\logo.png");
new ToastContentBuilder()
.AddArgument("action", "viewConversation")
.AddArgument("conversationId", 9813)
.AddText(title)
.AddText(message + " URL:" + url)
.AddAppLogoOverride(new Uri(imageUri))
.AddHeroImage(new Uri(imageUri))
.AddButton(new ToastButton()
.SetContent("Open URL")
.SetProtocolActivation(new Uri(url))
)
.Show();
结果:
可能有点晚了,但我对吐司有同样的问题,如果用户关闭了通知,不确定它是否有帮助。
为了表达祝酒词,我试了一下成功了:Tulpep.NotificationWindow
效果很好,您添加一个控件并访问所有参数,并且能够显示图像(并调整大小)。
下面是 link 的示例:https://www.c-sharpcorner.com/article/working-with-popup-notification-in-windows-forms/