WPF实现基础控件之托盘的示例代码

yizhihongxing

下面是WPF实现托盘的完整攻略:

一、前期准备

在开始编写代码之前,首先需要在项目中添加两个NuGet包:

这两个包的添加方式可以通过NuGet包管理器或在项目文件中手动添加。

二、定义托盘图标和菜单

在主窗口中添加托盘图标,并在托盘图标的上下文菜单中添加菜单项,可以通过以下代码实现:

<Window ...>
    ...
    <Window.Resources>
        <tray:TaskbarIcon x:Key="NotifyIcon" IconSource="icon.ico">
            <tray:TaskbarIcon.ContextMenu>
                <ContextMenu>
                    <MenuItem Header="打开窗口" Command="{Binding OpenWindowCommand}" />
                    <Separator />
                    <MenuItem Header="退出" Command="{Binding ExitCommand}" />
                </ContextMenu>
            </tray:TaskbarIcon.ContextMenu>
        </tray:TaskbarIcon>
    </Window.Resources>
    ...
</Window>

上述代码中,tray是指向Hardcodet.NotifyIcon.Wpf命名空间的XAML命名空间,icon.ico是托盘图标的路径。同时,在托盘图标的上下文菜单中定义了两个菜单项,分别绑定到主窗口ViewModel中的OpenWindowCommandExitCommand命令。

三、实现托盘功能

在主窗口ViewModel中,实现托盘功能需要完成以下几个步骤:

  1. 定义一个NotifyIcon对象,并在视图中绑定到托盘图标。
public class MainViewModel : INotifyPropertyChanged
{
    ...
    private readonly NotifyIcon _notifyIcon;

    public MainViewModel()
    {
        _notifyIcon = (NotifyIcon)Application.Current.FindResource("NotifyIcon");
        ...
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged([CallerMemberName] string propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    ...
}

在ViewModel的构造函数中获取在视图中定义的NotifyIcon对象,并保存到一个私有字段,以便后续使用。

  1. 定义OpenWindowCommand和ExitCommand命令,并实现相应的功能。
public class MainViewModel : INotifyPropertyChanged
{
    ...
    public ICommand OpenWindowCommand => new DelegateCommand(() =>
    {
        // 显示或激活主窗口
        var mainWindow = Application.Current.Windows.OfType<MainWindow>().FirstOrDefault();
        if (mainWindow != null)
        {
            mainWindow.Show();
            if (mainWindow.WindowState == WindowState.Minimized)
            {
                mainWindow.WindowState = WindowState.Normal;
            }
            mainWindow.Activate();
        }
    });

    public ICommand ExitCommand => new DelegateCommand(() =>
    {
        // 关闭应用程序
        Application.Current.Shutdown();
    });
    ...
}

上述代码中,OpenWindowCommand命令用于打开或激活主窗口,ExitCommand命令用于退出应用程序。

  1. 添加对WindowState的监听,实现窗口最小化时隐藏窗口并显示托盘图标。
public class MainViewModel : INotifyPropertyChanged
{
    ...
    public MainViewModel()
    {
        _notifyIcon = (NotifyIcon)Application.Current.FindResource("NotifyIcon");
        ...
        // 添加对WindowState的监听
        var mainWindow = Application.Current.Windows.OfType<MainWindow>().FirstOrDefault();
        if (mainWindow != null)
        {
            mainWindow.StateChanged += (sender, e) =>
            {
                switch (mainWindow.WindowState)
                {
                    case WindowState.Minimized:
                        mainWindow.Hide();
                        _notifyIcon.ShowBalloonTip("提示", "应用程序已最小化到托盘", BalloonIcon.Info);
                        break;
                    case WindowState.Normal:
                        _notifyIcon.HideBalloonTip();
                        break;
                }
            };
        }
    }
    ...
}

在构造函数中获取主窗口对象,并添加对WindowState的监听。当窗口状态变为最小化时,隐藏窗口并显示一个气泡提示,提醒用户应用程序已经最小化到托盘。

  1. 实现托盘图标的交互行为,如右键菜单打开主窗口。
public class MainViewModel : INotifyPropertyChanged
{
    ...
    public MainViewModel()
    {
        ...
        // 实现交互行为
        Interaction.GetBehaviors(_notifyIcon).Add(new TaskbarIconBehavior(OpenWindowCommand));
    }
    ...
}

public class TaskbarIconBehavior : Behavior<NotifyIcon>
{
    private readonly ICommand _command;

    public TaskbarIconBehavior(ICommand command)
    {
        _command = command;
    }

    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.TrayMouseDoubleClick += AssociatedObjectOnTrayMouseDoubleClick;
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        AssociatedObject.TrayMouseDoubleClick -= AssociatedObjectOnTrayMouseDoubleClick;
    }

    private void AssociatedObjectOnTrayMouseDoubleClick(object sender, RoutedEventArgs e)
    {
        _command.Execute(null);
    }
}

在主窗口ViewModel中,通过Behavior将托盘图标的交互行为定义为一个类,该类实现OnAttachedOnDetaching等相关方法,将双击图标打开主窗口的逻辑绑定到OpenWindowCommand命令上。

至此,WPF实现托盘的工作完毕。

四、示例说明

  1. 如何使用NotifyIcon显示气泡提示?

可以通过ShowBalloonTip方法显示气泡提示,方法参数包括提示标题、提示消息和提示图标。例如:

_notifyIcon.ShowBalloonTip("提示", "这是一条气泡提示", BalloonIcon.Info);
  1. 如何在托盘图标上添加自定义图标?

可以通过在托盘图标的XAML中指定IconSource属性实现自定义图标。例如:

<tray:TaskbarIcon IconSource="my_icon.ico">

其中my_icon.ico是自定义图标的文件名。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:WPF实现基础控件之托盘的示例代码 - Python技术站

(1)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • c++学习(八)(c语言部分)之图形库

    下面是关于 C++ 学习(八)(C 语言部分)之图形库的完整攻略,包含两个示例说明。 图形库 在 C 语言中,你可以使用图形库来创建基本的图形界面。图形库是一个软件库,它提供了一组函数,可以用来绘制图形、文本和其他图形元素。在 Windows 系统中,你可以使用 WinAPI 来创建图形界面,在 Linux 系统中,你可以使用 X Window System…

    other 2023年5月8日
    00
  • python的继承详解

    Python的继承详解 什么是继承 继承是面向对象编程中的重要概念之一。它允许子类(派生类)从父类(基类)那里继承属性和方法,并且可以在此基础上进行拓展或修改。继承是代码复用的一种方式,可以减少代码量,提高代码的可维护性和可扩展性。 Python中的继承 Python中的继承和其他面向对象语言的继承类似,可以通过关键字class来定义一个类,并使用括号来指定…

    other 2023年6月26日
    00
  • 科比遗体已安葬2月24日举行悼念仪式

    科比遗体已安葬2月24日举行悼念仪式 科比·布莱恩特和他的女儿吉安娜在2020年1月26日的一场直升机坠毁事故中不幸去世。近日,科的遗体已经安葬,并将于2月24日举行悼念仪式。以下是详细的攻略,包含两个示例说明。 科比遗体安葬的过程 科比的遗体安葬的过程如下: 科比的遗体在1月31日被火化。 科比的家人和朋友在2月7日举行了私人葬礼,安葬在洛杉矶的太平洋帕利…

    other 2023年5月8日
    00
  • 关闭网站的wscript.shell命令行执行

    关闭网站的wscript.shell命令行执行指的是防止攻击者通过网站运行wscript.shell对象来执行任意命令,从而实施攻击的一种方法。以下是关闭网站wscript.shell命令行执行的完整攻略: 1. 禁止服务器上WScript.Shell对象的访问 在服务器上禁止WScript.Shell对象的访问是防止攻击者利用该对象执行任意命令的有效方法。…

    other 2023年6月26日
    00
  • TPLink路由器隐藏wifi用户名的方法

    关于“TPLink路由器隐藏wifi用户名的方法”的完整攻略,我来详细讲解一下。 步骤一:打开TPLink路由器的管理页面 首先,我们需要打开TPLink路由器的管理界面。一般情况下,我们可以在浏览器的地址栏里输入“192.168.1.1”(也可能是“192.168.0.1”)来进入。登录时需要输入用户名和密码。如果你从未更改过路由器的管理密码,那么可以尝试…

    other 2023年6月27日
    00
  • win7注册表有哪些常用设置?

    当今使用最广泛的Windows操作系统之一是Windows 7,其包含许多有用的功能,允许用户对操作系统进行配置。其中最重要的配置文件之一是注册表。注册表是操作系统中的一种数据库,用于存储各种设置,包括Windows 7故障排除所需的所有信息。下面是Windows 7注册表的常见设置,可以帮助用户更好地优化系统性能,实现个性化需求。 1. 自动登录 自动登录…

    other 2023年6月27日
    00
  • lambda动态表达式(排序)

    Lambda动态表达式(排序) 在程序开发中,经常需要对集合中的元素进行排序。对于基本类型的数组,可以使用Java中的Arrays.sort()方法进行排序。然而,对于自定义类型的元素,需要实现Comparable接口来实现排序,这会增加代码的复杂性。此时,我们可以使用Lambda动态表达式来实现排序功能。 Lambda表达式是Java8引入的一个重要特性,…

    其他 2023年3月28日
    00
  • vundle简介安装

    Vundle是一款用于管理Vim插件的工具,可以方便地安装、更新和删除Vim插件。以下是Vundle的简介、安装和使用的完整攻略,包含两个示例说明: 简介 Vundle是一款轻量级的Vim插件管理器,可以方便地安装、更新和删除Vim插件。Vundle使用Vim脚本编写,可以与Git版本控制系统集成,支持自动安装和更新插件。 安装 安装Vundle需要执行以下…

    other 2023年5月9日
    00
合作推广
合作推广
分享本页
返回顶部