Как создать значок системного лотка WPF, если нет главного окна хоста

Фон

У нас есть приложение, которое сидит в фоновом режиме и использует FileSystemWatcher для отслеживания папки для новых файлов, когда появляется новый файл, который порождает окно.

Что мне нужно сделать, так это создать значок в системном трее для этого приложения, чтобы мы могли добавлять к нему простые элементы контекстного меню (возможность закрыть приложение, не входя в диспетчер задач, является самой большой).

Вопрос

Все результаты поиска, как реализовать значок в системном трее, указывают на примеры того, как добавить его в окно WPF, а не в самом приложении, поскольку мое приложение не имеет главного окна и порождает окна при возникновении события как я могу реализовать это?

Ответ 1

Установите приложение ShutdownMode на OnExplicitShutdown и отобразите значок в трее из Application.OnStartup. В этом примере используется NotifyIcon из WinForms, поэтому добавьте ссылку на System.Windows.Forms.dll и System.Drawing.dll. Кроме того, добавьте встроенный ресурс для значка Tray.

App.xaml

<Application x:Class="WpfTrayIcon.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             ShutdownMode="OnExplicitShutdown"
             >
    <Application.Resources>

    </Application.Resources>
</Application>

App.xaml.cs

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Windows;

using NotifyIcon = System.Windows.Forms.NotifyIcon;

namespace WpfTrayIcon
{
    public partial class App : Application
    {
        public static NotifyIcon icon;

        protected override void OnStartup(StartupEventArgs e)
        {
            App.icon = new NotifyIcon();
            icon.Click += new EventHandler(icon_Click);
            icon.Icon = new System.Drawing.Icon(typeof(App), "TrayIcon.ico");
            icon.Visible = true;

            base.OnStartup(e);
        }

        private void icon_Click(Object sender, EventArgs e)
        {
            MessageBox.Show("Thanks for clicking me");
        }
    }
}