74

I have a .ico file that is embedded as a resource (build action set to resource). I am trying to create a NotifyIcon. How can I reference my icon?

notifyIcon = new NotifyIcon();
notifyIcon.Icon = ??     // my icon file is called MyIcon.ico and is embedded
Dave Clemmer
  • 3,741
  • 12
  • 49
  • 72
ScottG
  • 10,711
  • 25
  • 82
  • 111
  • See similar question here: [enter link description here][1] [1]: http://stackoverflow.com/questions/1127647/convert-system-drawing-icon-to-system-media-imagesource – PatTheFrog Oct 02 '13 at 16:00

5 Answers5

116

Your icon file should be added to one of your project assemblies and its Build Action should be set to Resource. After adding a reference to the assembly, you can create a NotifyIcon like this:

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 );
user13125
  • 1,192
  • 1
  • 8
  • 4
  • 13
    Don't forget to dispose of iconStream once the icon is created. – devios1 Jul 23 '10 at 03:25
  • Thanks to this example I finally got how to get a resource in a referenced assembly of my application: new Uri( "pack://application:,,,/YourReferencedAssembly;component/YourPossibleSubFolder/YourResourceFile.ico") – Andrea Antonangeli Mar 19 '15 at 11:53
  • Does this allow the icon to have multiple resolutions? – tofutim Feb 27 '16 at 00:54
  • @tofutim Nope. None of the possible approaches use the 16px icon when there's also a 32px version in the icon file. Windows and icons is a shiny but sad story. – ygoe Jul 19 '20 at 07:52
22

A common usage pattern is to have the notify icon the same as the main window's icon. The icon is defined as a PNG file.

To do this, add the image to the project's resources and then use as follows:

var iconHandle  = MyNamespace.Properties.Resources.MyImage.GetHicon();
this.notifyIcon.Icon = System.Drawing.Icon.FromHandle(iconHandle);

In the window 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">
Thomas Bratt
  • 48,038
  • 36
  • 121
  • 139
  • 7
    Note that you should add the icon using the Resources designer and then set the build action to Resource for this to work. – Scott Munro Jan 26 '10 at 18:05
  • Thanks! This is a really nice way of using a tray icon. Just a note: I couldn't call GetHicon() but the following works just as well: `IntPtr iconHandle = Properties.Resources.SystemTray.Handle; my_notifyIcon.Icon = System.Drawing.Icon.FromHandle(iconHandle);` – mickeymicks Nov 03 '22 at 15:31
14

Well, you don't want to use the resx style resources: you just stick the ico file in your project in a folder (lets say "ArtWork") and in the properties, set the Build Action to "Resources" ...

Then you can reference it in XAML using PACK URIs ... "pack://application:,,,/Artwork/Notify.ico"

See here: http://msdn.microsoft.com/en-us/library/aa970069.aspx and the sample

If you want to be a little bit more ... WPF-like, you should look into the WPF Contrib project on CodePlex which has a NotifyIcon control which you can create in XAML and which uses standard WPF menus (so you can stick "anything" in the menu).

Jaykul
  • 15,370
  • 8
  • 61
  • 70
4

If you are just looking for the simple answer, I think this is it where MyApp is your application name and where that's the root namespace name for your application. You have to use the pack URI syntax, but it doesn't have to be that complicated to pull an icon out of your embedded resources.

    <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">
Mike Sage
  • 251
  • 2
  • 8
2

I created a project here and used an embedded resource (build action was set to Embedded Resource, rather than just resource). This solution doesn't work with Resource, but you may be able to manipulate it. I put this on the OnIntialized() but it doesn't have to go there.

//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;
    }
shinybluesphere
  • 355
  • 3
  • 11
  • 2
    Just an FYI - I read in my MS WPF MCTS training kit not to use Embedded Resources because it uses a different resource management scheme that is less accessible from WPF. Not sure what that means, but just passing along – ScottG Sep 16 '08 at 18:48
  • @ScottG Using URI may not work if you want to load resource before the main window is created. Therefore you need to embed the icon and loaded as described by blackSphere. In my case, I have to load icon in my ApplicationContext for my tray application. – Supawat Pusavanno Mar 17 '15 at 10:10