get the solution


Tray Icon mit WPF

By
on Regards: .NET Framework; Archive; C#;

Es gibt zwei verbreitete Methoden ein Tray Icon mit WPF zu realisieren. Die erste ist man erstellt im WPF Window das Tray Icon Objekt. Darin wird das Tray Icon Objekt gehostet. Die Nachteile:

  • Code ist nicht gut getrennt Tray Icon / Window
  • Will man nur das Tray Icon zum Programmstart anzeigen muss das Fenster versteckt werden

Die bessere Variante ist, in der App.xaml.cs die Methode OnStartup zu überschreiben und von dort aus das Tray Icon Objekt zu initialisieren. Nun kann man beliebig viele Fenster über das Tray Icon erstellen.

Das ganze realisiert man so:

  1. Projekttyp “Neue WPF Anwendung” erstellen
  2. Das vorhandene Window kann man wie man will löschen oder stehen lassen, wenn man dieses später benötigt
  3. In der App.xaml entfernen wir den Eintrag StartupUri=”Window1.xaml”
  4. Damit verhindern wir, dass beim Programmstart das Fenster Window1 erstellt und angezeigt wird.
  5. Für das TrayIcon verwenden wir das Objekt NotifyIcon welches sich in der Libary System.Windows.Forms befindet.
  6. Wir fügen also zu den Verweisen ->Rechter Mausklick -> Verweis hinzufügen -> System.Windows.Forms und System.Drawing hinzu damit wir auch das Icon setzen können

Ich habe eine kleine Tray Icon Klasse geschrieben, damit man schnell ein paar ContextMenu einträge zum Tray Icon hinzufügen kann. Dazu erstellen wir uns eine neue Klassen-Datei namens Tray.cs und fügen folgenden Code ein.

        using System.Windows.Forms;
	using System;
	 
	public class Tray
	{
	    private NotifyIcon _notico;
	    private bool _Animate = false;
	    private ContextMenu _contextMenu = new ContextMenu();
	 
	    public Tray()
	    {
	        Initialize();
	    }
	    public Tray(System.Drawing.Icon pIcon)
	    {
	        Initialize();
	        _notico.Icon = pIcon;
	    }
	    /// <summary>
	    /// Initialisiert das NotifyIcon
	    /// </summary>
	    private void Initialize()
	    {
	        // NotifyIcon erzeugen
	        _notico = new NotifyIcon();
	        _notico.Visible = true;
	 
	        ContextMenu contextMenu = new ContextMenu();
	 
	        // Kontextmenüeinträge erzeugen
	 
	        _notico.ContextMenu = _contextMenu;
	 
	    }
	    public void CreateMenuItem(String pName)
	    {
	        MenuItem menuItem = new MenuItem();
	        menuItem = new MenuItem();
	        menuItem.Index = 1;
	        menuItem.Name = pName;
	        menuItem.Text = "&" + menuItem.Name;
	 
	        _contextMenu.MenuItems.Add(menuItem);
	    }
	    public void CreateMenuItem(String pName, bool pTrue)
	    {
	        MenuItem menuItem = new MenuItem();
	        menuItem.Index = 2;
	        menuItem.Name = pName;
	        menuItem.Text = "&" + menuItem.Name;
	        menuItem.Click += (sender, e) =>
	        {
	            MenuItem m = (MenuItem)sender;
	            m.Checked = !m.Checked;
	        };
	        menuItem.Checked = pTrue;
	 
	        _contextMenu.MenuItems.Add(menuItem);
	    }
	    public NotifyIcon NotifyIcon
	    {
	        get
	        {
	            return _notico;
	        }
	    }
	}

Jetzt öffnen wir die App.xaml.cs Datei und überschreiben die Methode OnStartUp().

Damit unser Programm nicht beendet wird, wenn man ein erstelltes Fenster schließt, müssen wir die Propertie

ShutdownMode

entsprechend setzen. Wir setzen die Propertie deshalb auf den Wert 

OnExplicitShutdown

.

Damit das Tray Icon im Tray überhaupt sichtbar ist, benötigen wir ein Icon. Man kann ein neues Icon direkt im Vs.net erstellen oder ein vorhandenes hinzufügen. Wie man das Icon ins Programm ladet bleibt jedem selber überlassen. Ich lade das Icon einfachheitshalber aus einer Datei.

Danach erstellen wir das Tray Objekt und übergeben das Icon, welches ich aus der Datei geladen habe.

Nun können wir, auf die Tray Methoden zugreifen und beliebig viele ContextMenüs erstellen.

Über die Propertie NotifyIcon der Klasse Tray können wir auf die MenüItems zugreifen und deren verhalten bestimmen. Z.B, wenn man auf ein Menüitem klickt, dass ein neues Fenster erstellt wird, oder dass die komplette Applikation mit samt Tray Icon geschlossen wird.

Das sieht dann so aus:

        using System;
	using System.Collections.Generic;
	using System.Configuration;
	using System.Data;
	using System.Linq;
	using System.Windows;
	using System.Drawing;
	 
	namespace Tray_Icon_WPF
	{
	    /// <summary>
	    /// Interaction logic for App.xaml
	    /// </summary>
	    public partial class App : Application
	    {
	        protected override void OnStartup(StartupEventArgs e)
	        {
	            this.ShutdownMode = ShutdownMode.OnExplicitShutdown;
	 
	            //Icon laden
	            Icon icon = Icon.ExtractAssociatedIcon(@"C:UsersmartinDocumentsVisual Studio 2008BlogTray Icon WPFTray Icon WPFIcon1.ico"); 
	 
	            //trayicon erstellen und icon laden
	            Tray tray = new Tray(icon);
	 
	            tray.CreateMenuItem("Fenster aufrufen");
	            tray.CreateMenuItem("Beenden");
	 
	            //Menuitem Fenster aufrufen suchen, zugreifen Click Event anmelden und delegate setzen
	            tray.NotifyIcon.ContextMenu.MenuItems.Find("Fenster aufrufen", true).First().Click += (sender, eargs) =>
	            {
	                Window1 window = new Window1();
	                window.Show();
	 
	            };
	 
	            //Menuitem Beenden suchen, zugreifen Click Event anmelden und delegate setzen
	            tray.NotifyIcon.ContextMenu.MenuItems.Find("Beenden", true).First().Click += (sender, eargs) =>
	            {
	                //Icon aus tray löschen
	                tray.NotifyIcon.Dispose();
	                Environment.Exit(0);
	            };

	            base.OnStartup(e);
	        }
	    }
	}

Das Demo Projekt kann man hier herunterladen. Wenn ihr die Demo ausführt, müsst ihr den Pfad zum Icon anpassen. Über Fragen, Anregungen, Kritik freu ich mich.

Links:
Guter Artikel über das Tray Icon, allerdings wird der ShutdownMode nicht erwähnt
http://www.codecomplete.de/blogs/xamlblog/archive/2008/12/15/wpfanwendung-mit-trayicon.aspx
So sollte es meiner Meinung nicht machen (Code im Window)
http://possemeeg.wordpress.com/2007/09/06/minimize-to-tray-icon-in-wpf/