C# 实现WPF App最小化托盘测试

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.


右键弹出菜单:



代码可响应任何一个菜单的事件。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,658评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,482评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,213评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,395评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,487评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,523评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,525评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,300评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,753评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,048评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,223评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,905评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,541评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,168评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,417评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,094评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,088评论 2 352

推荐阅读更多精彩内容