WPF: Anwendung mit Systray-Icon ausstatten

25.12.2008 von Richard

Je nach Anwendung können Systray-Icons eine sehr bequeme Art der Steuerung darstellen. Daher dachte ich mir “bauste dir eben auch so ein Ding in dein Tool ein”. Fragt sich nur, wie man das am geschicktesten realisiert. Vermutlich könnte man das mit reinem XAML irgendwie lösen. Das sehe ich allerdings nicht als die optimale Lösung an, da mir das in dieser Hinsicht zu unflexibel ist. Also muss C# mit Windows.Forms herhalten.

Ein NotifyIcon ist schnell erzeugt und betitelt. Doch wie sieht es mit Icon und Kontextmenü aus? Das erfordert ein paar mehr Zeilen Code, erst recht, wenn man ein bereits eingebundenes Icon (bspw. das der Anwendung selbst) verwenden möchte. Ich gehe hierbei auf die Situation ein, dass sich das Icon in den eigenen Ressourcen von Expression Blend befindet.

Fangen wir ganz vorne an. Ein NotifyIcon lässt sich mit diesem Code erzeugen:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
private static NotifyIcon notifyIcon = new NotifyIcon();
 
public MainWindow()
{
    // info when mouse hits the icon
    notifyIcon.Text = "Programmtitel";
 
    // double click: bring application back to front
    notifyIcon.MouseDoubleClick += new
        System.Windows.Forms.MouseEventHandler(openFromTray);
 
    // create context menu and add items
    System.Windows.Forms.ContextMenu myContextMenu = new
        System.Windows.Forms.ContextMenu();
 
    myContextMenu.MenuItems.Add(0, new System.Windows.Forms.MenuItem("Show",
        new EventHandler(openFromTray)));
    myContextMenu.MenuItems.Add(1, new System.Windows.Forms.MenuItem("Exit",
        new EventHandler(systrayExit)));
 
    notifyIcon.ContextMenu = myContextMenu;
}

Die beiden Funktionen zum Wiederherstellen oder Schließen der Anwendung könnten beispielsweise so aussehen:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
private void openFromTray(object sender, EventArgs e)
{
    notifyIcon.Visible = false;
    this.ShowInTaskbar = true;
    this.Show();
    this.WindowState = WindowState.Normal;
}
protected void systrayExit(object sender, EventArgs e)
{
    notifyIcon.Visible = false;
    this.Close();
}

Damit das Ganze überhaupt funktioniert, benötigen wir hierzu den Namespace System.Windows.Forms, da sowohl die Klasse ContextMenu als auch die Klasse NotifyIcon von Windows.Forms stammen. Dies lässt sich mit der Zeile using System.Windows.Forms; am Anfang des Dokuments erledigen. Erhält man die Fehlermeldung, dass Forms im Namespace System.Windows nicht vorhanden ist, muss der nötige Verweis erst dem Projekt hinzugefügt werden:

Verweis hinzufügen 1 Verweis hinzufügen 2

Sollte der Compiler das Erzeugen des NotifyIcon nicht schlucken muss NotifyIcon zu System.Windows.Forms.NotifyIcon erweitert werden.

Soweit so gut, jetzt braucht es nur noch ein passendes Icon. Eigentlich ist die Sache ganz einfach:

 1 notifyIcon.Icon = new Icon("Icon.ico");

Schwieriger wird es erst, wenn ich mein Icon aus den Ressourcen, die ich in Blend eingerichtet habe herausnehmen möchte.

Blend Resources

Gehen wir von der Situation wie im Bild zu sehen aus. Das Icon befindet sich demnach im Ordner "Images". Um dieses Icon zu verwenden benötigen wir hierfür einen Ressourcenstreamer , der auf diese Ressourcen zugreifen kann, um sie gefügig zu machen.

 1
 2
 3
 4
 5
 6
 7
try
{
    Stream iconStream = System.Windows.Application.GetResourceStream(new
        Uri("Images/Icon.ico", UriKind.Relative)).Stream;
    notifyIcon.Icon = new System.Drawing.Icon(iconStream);
}
catch { }

Der try-catch-Block empfiehlt sich hier - wie eigentlich immer bei Zugriff auf Dateien. Für das Erzeugen des Icons aus dem Stream iconStream muss ggf. wieder ein Verweis hinzugefügt werden (siehe oben). Diesmal System.Drawing.

Systray-Icon

Wie erwünscht, erscheint das Icon und das Kontextmenü. Ziel erreicht. :-)

Damit wäre ich am Ende. Vielleicht konnte ich dem einen oder anderen helfen. Fällt mir noch etwas ein, werde ich den Artikel erweitern. Verbesserungsvorschläge sind wie immer willkommen.

Fin.

Geschrieben in C#, Expression Blend |

Kommentare sind geschlossen.