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

如何实现MAUI应用在MacOS(Mac Catalyst)下后台运行于系统托盘?

MAUI系统托盘应用:MacOS平台关闭窗口后保留托盘运行的实现方案

我正在开发一款可运行于系统托盘的MAUI应用,已在Windows平台实现关闭主窗口后仍保留系统托盘运行的功能,但MacOS平台的对应功能无法完成。开发时参考了WeatherTwentyOne项目构建系统托盘,以下是Windows平台的实现代码:

public App()
{
    InitializeComponent();
    MainPage = new AppShell();
}

protected override Window CreateWindow(IActivationState activationState)
{
    Window window = base.CreateWindow(activationState);

#if WINDOWS
    window.Created += (s, e) =>
    {
        var handle = WinRT.Interop.WindowNative.GetWindowHandle(window.Handler.PlatformView);
        var id = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(handle);
        var appWindow = Microsoft.UI.Windowing.AppWindow.GetFromWindowId(id);
        appWindow.Closing += (s, e) =>
        {
            e.Cancel = true;
            appWindow.Hide();
        };
    };
#endif
    return window;
}

MacOS平台实现方案

1. 拦截窗口关闭事件,阻止应用退出

在CreateWindow方法中添加MacOS平台专属代码,拦截窗口断开场景的事件,取消默认退出行为并隐藏窗口:

protected override Window CreateWindow(IActivationState activationState)
{
    Window window = base.CreateWindow(activationState);

#if WINDOWS
    window.Created += (s, e) =>
    {
        var handle = WinRT.Interop.WindowNative.GetWindowHandle(window.Handler.PlatformView);
        var id = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(handle);
        var appWindow = Microsoft.UI.Windowing.AppWindow.GetFromWindowId(id);
        appWindow.Closing += (s, e) =>
        {
            e.Cancel = true;
            appWindow.Hide();
        };
    };
#elif MACCATALYST
    window.Created += (s, e) =>
    {
        var platformWindow = window.Handler.PlatformView as UIKit.UIWindow;
        platformWindow.WindowScene.Delegate = new WindowSceneDelegate(platformWindow);
    };
#endif
    return window;
}

2. 实现自定义WindowSceneDelegate

创建一个继承自UIKit.UIWindowSceneDelegate的类,重写WillDisconnect方法来控制窗口关闭时的行为:

#if MACCATALYST
public class WindowSceneDelegate : UIKit.UIWindowSceneDelegate
{
    private readonly UIKit.UIWindow _window;

    public WindowSceneDelegate(UIKit.UIWindow window)
    {
        _window = window;
    }

    public override void WillDisconnect(UIKit.UIScene scene, UIKit.UISceneSession session, UIKit.UISceneDisconnectOptions options)
    {
        if (options.ShouldDisconnect)
        {
            // 隐藏窗口而非关闭应用
            _window.Hidden = true;
            // 维持应用后台存活
            UIKit.UIApplication.SharedApplication.SetKeepAliveTimeout(600, () => {});
        }
        base.WillDisconnect(scene, session, options);
    }
}
#endif

3. 托盘图标点击恢复窗口

确保你的系统托盘实现中添加点击事件,用于重新显示隐藏的主窗口:

#if MACCATALYST
// 假设已初始化NSStatusItem作为托盘图标
var statusItem = AppKit.NSStatusBar.SystemStatusBar.CreateStatusItem(AppKit.NSStatusItemLength.Variable);
statusItem.Button.Image = AppKit.NSImage.ImageNamed("TrayIcon"); // 替换为你的托盘图标名称
statusItem.Button.Activated += (s, e) =>
{
    var mainWindow = App.Current.Windows.FirstOrDefault();
    if (mainWindow != null)
    {
        var platformWindow = mainWindow.Handler.PlatformView as UIKit.UIWindow;
        platformWindow.Hidden = false;
        platformWindow.MakeKeyAndVisible();
    }
};
#endif

额外配置

  • 打开MacOS项目的Info.plist,添加UIApplicationExitsOnSuspend键并设置值为NO,防止应用进入后台后被系统终止
  • 确保托盘图标已添加到MacOS项目的资源文件中,路径引用正确

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 19:25:23