创建基于系统托盘的WPF程序

最近都没怎么接触WPF了,闲来无事为以前做的WPF DEMO添加托盘管理。 

http://www.cnblogs.com/leeolevis/archive/2010/07/14/1777658.html 

其中,主要添加了NotificationAreaIcon类,代码如下:

复制代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Threading;
using Drawing = System.Drawing;
using Forms = System.Windows.Forms;

namespace WpfApplication1
{
    
/// <summary>
    
/// Represents a thin wrapper for <see cref="Forms.NotifyIcon"/>
    
/// </summary>
    [ContentProperty("Text")]
    [DefaultEvent(
"MouseDoubleClick")]
    
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
    }

  } 

复制代码

  

在主窗口上引用该命名控件 xmlns:l="clr-namespace:WpfApplication1"

在主窗口里添加如下代码

复制代码
        <l:NotificationAreaIcon
                      Text
="NotificationAreaApplication1"
                      Icon
="Resources\NotificationAreaIcon.ico"
                      MouseDoubleClick
="OnNotificationAreaIconDoubleClick" Grid.ColumnSpan="2">
            
<l:NotificationAreaIcon.MenuItems>
                
<forms:MenuItem Text="关于作者" Click="OnMenuItemAboutClick"/>
                
<forms:MenuItem Text="-" />
                
<forms:MenuItem Text="Open" Click="OnMenuItemOpenClick" DefaultItem="True" />
                
<forms:MenuItem Text="-" />
                
<forms:MenuItem Text="Exit" Click="OnMenuItemExitClick" />
            
</l:NotificationAreaIcon.MenuItems>

   </l:NotificationAreaIcon>  

复制代码

后台定义如下状态,并重载其Window类的OnStateChanged和OnClosing方法,代码如下:

复制代码
        WindowState lastWindowState;
        
bool shouldClose;

        
public MainWindow()
        {
            InitializeComponent();
            
this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
        }

        
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            DataBind();
        }

        
protected override void OnStateChanged(EventArgs e)
        {
            lastWindowState 
= WindowState;
        }

        
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
        {
            
if (!shouldClose)
            {
                e.Cancel 
= true;
                Hide();
            }

复制代码

并为托盘菜单添加事件:

复制代码
        protected void OnMenuItemAboutClick(object sender, EventArgs e)
        {
            
new Window1().Show();
        }

        
private void OnNotificationAreaIconDoubleClick(object sender, MouseButtonEventArgs e)
        {
            
if (e.ChangedButton == MouseButton.Left)
            {
                Open();
            }
        }

        
private void OnMenuItemOpenClick(object sender, EventArgs e)
        {
            Open();
        }

        
private void Open()
        {
            Show();
            WindowState 
= lastWindowState;
        }

        
private void OnMenuItemExitClick(object sender, EventArgs e)
        {
            shouldClose 
= true;
            Close();

复制代码

完成,运行我们的程序,看到托盘已经有我们添加的菜单了:

 

 DEMO:/Files/leeolevis/NotifiWpfAppl.rar

posted @   leeolevis  阅读(2528)  评论(3编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示