WPF 需要添加Windows.Forms 组件。
xmlns:winForm ="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
前台XAML代码如下:
<Window x:Class="WpfApp.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" xmlns:local="clr-namespace:WpfApp" xmlns:winForm ="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms" xmlns:drawing="clr-namespace:System.Drawing;assembly=System.Drawing" StateChanged="Window_StateChanged" SizeChanged="Window_SizeChanged" mc:Ignorable="d" Title="最小化到托盘测试" Height="250" Width="400"> <Grid> <local:NotificationAreaIcon x:Name="notfyicon" Text="我是测试代码" Icon="red.ico" MouseDoubleClick="NotificationAreaIcon_MouseDoubleClick"> <local:NotificationAreaIcon.MenuItems> <winForm:MenuItem x:Name="MenuIteOnline" Click="MenuIteOnline_Click"> <winForm:MenuItem.Text>在线</winForm:MenuItem.Text> </winForm:MenuItem> <winForm:MenuItem Text="离开" x:Name="MenuItemLeave" Click="MenuItemLeave_Click"/> <winForm:MenuItem Text="请勿打扰" x:Name="MenuItemNoBother" Click="MenuItemNoBother_Click"/> <winForm:MenuItem Text="忙碌" x:Name="MenuItemBusy" Click="MenuItemBusy_Click"/> <winForm:MenuItem Text="隐身" x:Name="MenuItemHidden" Click="MenuItemHidden_Click"/> <winForm:MenuItem Text="离线" x:Name="MenuItemOffline" Click="MenuItemOffline_Click"/> <winForm:MenuItem Text="关于" x:Name="MenuItemAboutUs" Click="MenuItemAboutUs_Click"/> <winForm:MenuItem Text="退出" x:Name="MenuItemExit" Click="MenuItemExit_Click"/> </local:NotificationAreaIcon.MenuItems> </local:NotificationAreaIcon> </Grid> </Window>
添加实现的类 NotificationAreaIcon.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using Drawing = System.Drawing;
using Forms = System.Windows.Forms; //Forms.NotifyIcon
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Markup;
namespace WpfApp
{
public class NotificationAreaIcon : FrameworkElement
{
Forms.NotifyIcon notifyIcon;
public static readonly RoutedEvent MouseClickEvent = EventManager.RegisterRoutedEvent(
"MouseClick", RoutingStrategy.Bubble, typeof(MouseButtonEventHandler), typeof(NotificationAreaIcon));
public static readonly RoutedEvent MouseDoubleClickEvent = EventManager.RegisterRoutedEvent(
"MouseDoubleClick", RoutingStrategy.Bubble, typeof(MouseButtonEventHandler), typeof(NotificationAreaIcon));
public static readonly DependencyProperty IconProperty =
DependencyProperty.Register("Icon", typeof(ImageSource), typeof(NotificationAreaIcon));
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(NotificationAreaIcon));
public static readonly DependencyProperty FormsContextMenuProperty =
DependencyProperty.Register("MenuItems", typeof(List<Forms.MenuItem>), typeof(NotificationAreaIcon), new PropertyMetadata(new List<Forms.MenuItem>()));
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
// Create and initialize the window forms notify icon based
notifyIcon = new Forms.NotifyIcon();
notifyIcon.Text = Text;
if (!DesignerProperties.GetIsInDesignMode(this))
{
notifyIcon.Icon = FromImageSource(Icon);
}
notifyIcon.Visible = FromVisibility(Visibility);
if (this.MenuItems != null && this.MenuItems.Count > 0)
{
notifyIcon.ContextMenu = new System.Windows.Forms.ContextMenu(this.MenuItems.ToArray());
}
notifyIcon.MouseDown += OnMouseDown;
notifyIcon.MouseUp += OnMouseUp;
notifyIcon.MouseClick += OnMouseClick;
notifyIcon.MouseDoubleClick += OnMouseDoubleClick;
Dispatcher.ShutdownStarted += OnDispatcherShutdownStarted;
}
private void OnDispatcherShutdownStarted(object sender, EventArgs e)
{
notifyIcon.Dispose();
}
private void OnMouseDown(object sender, Forms.MouseEventArgs e)
{
OnRaiseEvent(MouseDownEvent, new MouseButtonEventArgs(
InputManager.Current.PrimaryMouseDevice, 0, ToMouseButton(e.Button)));
}
private void OnMouseUp(object sender, Forms.MouseEventArgs e)
{
OnRaiseEvent(MouseUpEvent, new MouseButtonEventArgs(
InputManager.Current.PrimaryMouseDevice, 0, ToMouseButton(e.Button)));
}
private void OnMouseDoubleClick(object sender, Forms.MouseEventArgs e)
{
OnRaiseEvent(MouseDoubleClickEvent, new MouseButtonEventArgs(
InputManager.Current.PrimaryMouseDevice, 0, ToMouseButton(e.Button)));
}
private void OnMouseClick(object sender, Forms.MouseEventArgs e)
{
OnRaiseEvent(MouseClickEvent, new MouseButtonEventArgs(
InputManager.Current.PrimaryMouseDevice, 0, ToMouseButton(e.Button)));
}
private void OnRaiseEvent(RoutedEvent handler, MouseButtonEventArgs e)
{
e.RoutedEvent = handler;
RaiseEvent(e);
}
public List<Forms.MenuItem> MenuItems
{
get { return (List<Forms.MenuItem>)GetValue(FormsContextMenuProperty); }
set { SetValue(FormsContextMenuProperty, value); }
}
public ImageSource Icon
{
get { return (ImageSource)GetValue(IconProperty); }
set { SetValue(IconProperty, value); }
}
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public event MouseButtonEventHandler MouseClick
{
add { AddHandler(MouseClickEvent, value); }
remove { RemoveHandler(MouseClickEvent, value); }
}
public event MouseButtonEventHandler MouseDoubleClick
{
add { AddHandler(MouseDoubleClickEvent, value); }
remove { RemoveHandler(MouseDoubleClickEvent, value); }
}
#region Conversion members
private static Drawing.Icon FromImageSource(ImageSource icon)
{
if (icon == null)
{
return null;
}
Uri iconUri = new Uri(icon.ToString());
return new Drawing.Icon(Application.GetResourceStream(iconUri).Stream);
}
private static bool FromVisibility(Visibility visibility)
{
return visibility == Visibility.Visible;
}
private MouseButton ToMouseButton(Forms.MouseButtons button)
{
switch (button)
{
case Forms.MouseButtons.Left:
return MouseButton.Left;
case Forms.MouseButtons.Right:
return MouseButton.Right;
case Forms.MouseButtons.Middle:
return MouseButton.Middle;
case Forms.MouseButtons.XButton1:
return MouseButton.XButton1;
case Forms.MouseButtons.XButton2:
return MouseButton.XButton2;
}
throw new InvalidOperationException();
}
#endregion Conversion members
}
}
Windows UI 后台代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApp
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.ShowInTaskbar = false;
}
private void Window_StateChanged(object sender, EventArgs e)
{
if (this.WindowState == WindowState.Minimized)
{
this.Hide();
}
if (this.WindowState == WindowState.Normal || this.WindowState == WindowState.Maximized)
{
this.Show();
this.Activate();
}
}
private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (this.WindowState == WindowState.Minimized)
{
this.ShowInTaskbar = false;
this.Hide();
this.notfyicon.Visibility = Visibility.Visible;
}
}
//双击托盘图标恢复需要响应notifyIcon的DoubleClick消息
private void NotificationAreaIcon_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
if (this.WindowState == WindowState.Minimized)
{
this.Show();
WindowState = WindowState.Normal;
this.notfyicon.Visibility = Visibility.Hidden;
this.ShowInTaskbar = true;
}
}
private void MenuItemLeave_Click(object sender, EventArgs e)
{
MessageBox.Show("提示离线!");
}
private void MenuItemNoBother_Click(object sender, EventArgs e)
{
MessageBox.Show("提示请勿打扰!");
}
private void MenuItemBusy_Click(object sender, EventArgs e)
{
MessageBox.Show("提示在忙!");
}
private void MenuItemHidden_Click(object sender, EventArgs e)
{
MessageBox.Show("提示隐身!");
}
private void MenuItemOffline_Click(object sender, EventArgs e)
{
MessageBox.Show("提示暂时离开!");
}
private void MenuItemAboutUs_Click(object sender, EventArgs e)
{
MessageBox.Show("提示关于我们!");
}
private void MenuItemExit_Click(object sender, EventArgs e)
{
this.Close();
}
private void MenuIteOnline_Click(object sender, EventArgs e)
{
MessageBox.Show("提示上线!");
}
}
}
运行测试如下:
最小化,在状态栏显示指定logo.
右键弹出菜单:
代码可响应任何一个菜单的事件。