如何在WPF中使用作为资源的图标?

74

我有一个.ico文件作为资源嵌入(构建操作设置为资源)。我想创建一个NotifyIcon。如何引用我的图标?

notifyIcon = new NotifyIcon();
notifyIcon.Icon = ??     // my icon file is called MyIcon.ico and is embedded

请参考以下类似的问题: 在此处输入链接说明 - PatTheFrog
5个回答

116

您的图标文件应该添加到您的项目程序集之一,并将其生成操作设置为资源。在添加对程序集的引用后,您可以像这样创建NotifyIcon:

System.Windows.Forms.NotifyIcon icon = new System.Windows.Forms.NotifyIcon();
Stream iconStream = Application.GetResourceStream( new Uri( "pack://application:,,,/YourReferencedAssembly;component/YourPossibleSubFolder/YourResourceFile.ico" )).Stream;
icon.Icon = new System.Drawing.Icon( iconStream );

13
创建图标后不要忘记处理 iconStream。 - devios1
多亏了这个例子,我终于知道如何获取我的应用程序中引用程序集中的资源了: new Uri( "pack://application:,,,/YourReferencedAssembly;component/YourPossibleSubFolder/YourResourceFile.ico") - Andrea Antonangeli
这个允许图标拥有多个分辨率吗? - tofutim
@tofutim 不行。当图标文件中还有32px版本时,没有一种可能的方法会使用16px图标。Windows和图标是一个闪亮但悲伤的故事。 - ygoe

22

常见的使用模式是将通知图标与主窗口的图标相同。这个图标是一个PNG文件。

要实现这一点,将图像添加到项目资源中,然后按以下方式使用:

var iconHandle  = MyNamespace.Properties.Resources.MyImage.GetHicon();
this.notifyIcon.Icon = System.Drawing.Icon.FromHandle(iconHandle);
在窗口的 XAML 中:
<Window x:Class="MyNamespace.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:local="clr-namespace:Seahorse"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="600"
Icon="images\MyImage.png">

7
请注意,您应该使用资源设计器添加图标,然后将构建操作设置为“资源”,才能使此功能正常工作。 - Scott Munro
谢谢!这是一种非常好的使用托盘图标的方式。 只是注意:我无法调用GetHicon(),但以下方法同样有效:IntPtr iconHandle = Properties.Resources.SystemTray.Handle; my_notifyIcon.Icon = System.Drawing.Icon.FromHandle(iconHandle); - mickeymicks

14

你不需要使用resx风格资源,只需将ico文件放置在项目文件夹中(假设为“ArtWork”),并在属性中将构建操作设置为“Resources”...

然后,您可以使用PACK URI在XAML中引用它... "pack://application:,,,/Artwork/Notify.ico"

请参见:http://msdn.microsoft.com/en-us/library/aa970069.aspx示例

如果您想更加符合WPF的风格,您可以查看CodePlex上的WPF Contrib项目,该项目具有一个NotifyIcon控件,您可以在XAML中创建该控件,并且可以使用标准WPF菜单(因此您可以将“任何东西”放在菜单中)。


4
如果你只是想要简单的答案,我认为这就是答案:MyApp是你的应用程序名称,那么它就是你的应用程序的根命名空间名称。你必须使用打包URI语法,但没有必要让从嵌入资源中提取图标变得复杂。
    <Window x:Class="MyApp.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Height="100"
    Width="200"
    Icon="pack://application:,,,/MyApp;component/Resources/small_icon.ico">

2

我在这里创建了一个项目,并使用了一个嵌入式资源(构建操作设置为嵌入式资源,而不仅仅是资源)。这个解决方案不能与资源一起使用,但你可能能够操纵它。我将其放在OnIntialized()上,但不一定非要放在那里。

//IconTest = namespace; exclamic.ico = resource 
System.IO.Stream stream = this.GetType().Assembly.GetManifestResourceStream("IconTest.Resources.exclamic.ico");

   if (stream != null)
   {
       //Decode the icon from the stream and set the first frame to the BitmapSource
       BitmapDecoder decoder = IconBitmapDecoder.Create(stream, BitmapCreateOptions.None, BitmapCacheOption.None);
       BitmapSource source = decoder.Frames[0];

       //set the source of your image
       image.Source = source;
    }

2
只是提醒一下 - 我在我的 MS WPF MCTS 培训套件中读到不要使用嵌入式资源,因为它使用了一种不太容易从 WPF 访问的不同资源管理方案。不确定这意味着什么,但只是传递一下。 - ScottG
@ScottG 如果您想在主窗口创建之前加载资源,则使用URI可能无法正常工作。因此,您需要像blackSphere所描述的那样嵌入图标并进行加载。在我的情况下,我必须在我的托盘应用程序的ApplicationContext中加载图标。 - Supawat Pusavanno

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接