You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何取消Microsoft.UI.Xaml.Window关闭事件?WinUI3窗口拦截方案

WinUI3拦截窗口关闭、仅通过托盘菜单退出的解决方案

核心思路

WinUI3的Microsoft.UI.Xaml.Window(及继承它的WindowEx)不支持WPF式的重写OnClosing方法,需通过订阅Closing事件拦截关闭操作,将窗口隐藏而非关闭,仅在托盘菜单触发时才真正退出程序。

具体实现步骤

1. 订阅窗口Closing事件

在MainWindow构造函数中添加事件订阅:

public MainWindow()
{
    InitializeComponent();

    AppWindow.SetIcon(Path.Combine(AppContext.BaseDirectory, "Assets/WindowIcon.ico"));
    Content = null;
    Title = "AppDisplayName".GetLocalized();

    // 订阅窗口关闭事件
    this.Closing += MainWindow_Closing;

    dispatcherQueue = Microsoft.UI.Dispatching.DispatcherQueue.GetForCurrentThread();
}

2. 实现Closing事件拦截逻辑

在事件处理方法中取消默认关闭行为,隐藏窗口:

private void MainWindow_Closing(object sender, WindowEventArgs e)
{
    // 取消窗口关闭操作
    e.Cancel = true;
    // 隐藏窗口到后台
    this.Hide();
}

3. 托盘菜单退出逻辑

在托盘菜单的「退出」按钮点击事件中,取消事件订阅后再关闭程序:

private void TrayExitMenuItem_Click(object sender, RoutedEventArgs e)
{
    // 取消Closing事件订阅,避免拦截本次关闭操作
    this.Closing -= MainWindow_Closing;
    // 关闭窗口
    this.Close();
    // 终止应用程序
    Application.Current.Exit();
}

完整修改后的MainWindow代码

public sealed partial class MainWindow : WindowEx
{
    private readonly Microsoft.UI.Dispatching.DispatcherQueue dispatcherQueue;

    public MainWindow()
    {
        InitializeComponent();

        AppWindow.SetIcon(Path.Combine(AppContext.BaseDirectory, "Assets/WindowIcon.ico"));
        Content = null;
        Title = "AppDisplayName".GetLocalized();

        // 订阅窗口关闭事件
        this.Closing += MainWindow_Closing;

        dispatcherQueue = Microsoft.UI.Dispatching.DispatcherQueue.GetForCurrentThread();
    }

    private void MainWindow_Closing(object sender, WindowEventArgs e)
    {
        // 拦截默认关闭行为,隐藏窗口到后台
        e.Cancel = true;
        this.Hide();
    }

    private void Settings_ColorValuesChanged(UISettings sender, object args)
    {
        // 跨线程调用,调度到当前应用线程执行
        dispatcherQueue.TryEnqueue(TitleBarHelper.ApplySystemThemeToCaptionButtons);
    }

    // 托盘菜单退出按钮点击事件
    private void TrayExitMenuItem_Click(object sender, RoutedEventArgs e)
    {
        this.Closing -= MainWindow_Closing;
        this.Close();
        Application.Current.Exit();
    }
}

注意事项

  • 需确保托盘图标功能已正确实现(WinUI3无内置托盘控件,可自行开发或使用第三方NuGet包)。
  • 若WindowEx有自定义窗口逻辑,需验证Hide()方法能正常隐藏窗口,不会触发额外关闭流程。

内容的提问来源于stack exchange,提问作者Jack251970

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 06:20:23