maui中怎么实现隐藏窗口
maui中怎么实现隐藏窗口 托盘隐藏窗口 系统托盘显示窗口
maui中怎么实现隐藏窗口 maui中怎么实现系统托盘显示窗口
关闭事件拦截,通过系统托盘图标右键退出关闭
#if WINDOWS
builder.ConfigureLifecycleEvents(events =>
{
events.AddWindows(wndLifeCycleBuilder =>
{
wndLifeCycleBuilder.OnWindowCreated(window =>
{
IntPtr nativeWindowHandle = WinRT.Interop.WindowNative.GetWindowHandle(window);
WindowId win32WindowsId = Win32Interop.GetWindowIdFromWindow(nativeWindowHandle);
AppWindow winuiAppWindow = AppWindow.GetFromWindowId(win32WindowsId);
// 保持标题栏和边框显示
window.ExtendsContentIntoTitleBar = false;
if (winuiAppWindow.Presenter is OverlappedPresenter p)
{
p.IsAlwaysOnTop = false;
p.IsResizable = true;
p.IsMaximizable = true;
p.IsMinimizable = true;
p.SetBorderAndTitleBar(true, true);
// 设置初始窗口大小和居中位置
var displayArea = DisplayArea.Primary;
var scalingFactor = ((MauiWinUIWindow)Application.Current?.Windows[0].Handler.PlatformView)?.GetDisplayDensity() ?? 1;
var width = 500 * scalingFactor;
var height = 700 * scalingFactor;
var centerX = (displayArea.WorkArea.Width - width) / 2;
var centerY = (displayArea.WorkArea.Height - height) / 2;
winuiAppWindow.MoveAndResize(new((int)centerX, (int)centerY, (int)width, (int)height), displayArea);
events.AddWindows(windows =>
{
WindowExtensions.Hwnd = nativeWindowHandle;
WindowExtensions.Show = () =>
{
WindowExtensions.BringToFront();
var displyArea = DisplayArea.Primary;
var scalingFactor = ((MauiWinUIWindow)Application.Current?.Windows[0].Handler.PlatformView)?.GetDisplayDensity() ?? 1;
var width = 500 * scalingFactor;
var height = 700 * scalingFactor;
// 右键打开时窗口居中显示
var centerX = (displyArea.WorkArea.Width - width) / 2;
var centerY = (displyArea.WorkArea.Height - height) / 2;
winuiAppWindow.MoveAndResize(new((int)centerX, (int)centerY, (int)width, (int)height), displyArea);
winuiAppWindow.Show();
};
WindowExtensions.Hide = () =>
{
winuiAppWindow.Hide();
};
WindowExtensions.Close = () =>
{
((MauiWinUIWindow)Application.Current?.Windows[0].Handler.PlatformView)?.Close();
};
windows.OnLaunched((_, _) =>
{
});
// 关闭事件拦截,通过系统托盘图标右键退出关闭,
windows.OnClosed((_, args) =>
{
Console.WriteLine( "");
var trayService = Application.Current?.Handler?.MauiContext?.Services?.GetService<ITrayService>();
//trayService.tray.dispose();
trayService.HideClickHandler?.Invoke();
args.Handled = true;
//Application.Current.Quit();
//var trayService = Application.Current?.Handler?.MauiContext?.Services?.GetService<ITrayService>();
//if (trayService != null && !trayService.isDispose)
//{
// args.Handled = true;
// WindowExtensions.Hide();
//}
// 正常的关闭行为,不再拦截
});
});
}
// 移除初始隐藏窗口的代码,让窗口正常显示
// winuiAppWindow.Hide(); // 注释掉这行
});
});
});
#endif 检查一下,为什么关闭事件 //Application.Current.Quit(); 如果不调用这个全局退出,就会报错
但是调用了全局退出,触发窗口隐藏 就没意义
我帮你梳理一下你这段 MAUI + WinUI3 的关闭事件逻辑问题。
你遇到的核心点是:
- OnClosed 事件如果不调用
Application.Current.Quit(),会报错。 - 但你真正想要的效果是 拦截关闭事件,不退出程序,而是隐藏窗口(比如托盘程序的常见逻辑)。
- 如果直接调用
Quit(),程序全局退出了,就失去了「最小化到托盘」的意义。
为什么会报错?
在 WinUI3 里,OnClosed 默认是触发 窗口销毁 → WinAppSDK 停止消息循环 → 整个进程结束。
你虽然 args.Handled = true,但实际上 WinAppSDK 内部已经准备好要销毁 MainWindow 了。
所以:
- 如果你不调用
Quit(),WinAppSDK 还以为窗口要销毁 → 导致异常。 - 如果你调用
Quit(),就正常退出 → 但这不符合你要的托盘模式。
正确处理方式
WinUI3 里 OnClosed 并不是「窗口关闭按钮事件」,而是「窗口真的被销毁后」才触发的。
👉 也就是说,你拦截错了事件。
你应该用 OnCloseRequested(即 WinUI 的 AppWindow.Closing 事件),在那个事件里拦截并隐藏窗口。
修改建议
在 OnWindowCreated 里加上这一段:
winuiAppWindow.Closing += (sender, args) =>
{
// 拦截关闭
args.Cancel = true;
// 隐藏窗口而不是销毁
winuiAppWindow.Hide();
// 通知托盘服务更新状态(如果有)
var trayService = Application.Current?.Handler?.MauiContext?.Services?.GetService<ITrayService>();
trayService?.HideClickHandler?.Invoke();
};
然后:
- 不要在
windows.OnClosed里写拦截逻辑,那是「已经销毁」后的回调,拦不住。 Application.Current.Quit()只在你 真正要退出应用(比如托盘菜单点“退出”)的时候调用。
✅ 总结:
- 用
AppWindow.Closing拦截关闭按钮 → 改成隐藏窗口。 Application.Current.Quit()只在「退出菜单」调用,而不是窗口的关闭按钮。windows.OnClosed可以保留,但那是程序真的要退出时的「清理收尾」事件。
要不要我帮你改写一份 完整可运行的托盘 + 关闭拦截方案(包含 TrayService 调用 + Hide/Show/Quit 三个入口)?
// 关闭事件拦截,通过系统托盘图标右键退出关闭,
windows.OnClosed((_, args) =>
{
var trayService = Application.Current?.Handler?.MauiContext?.Services?.GetService<ITrayService>();
trayService.tray.dispose();
//trayService.HideClickHandler?.Invoke();
Application.Current.Quit();
//var trayService = Application.Current?.Handler?.MauiContext?.Services?.GetService<ITrayService>();
//if (trayService != null && !trayService.isDispose)
//{
// args.Handled = true;
// WindowExtensions.Hide();
//}
// 正常的关闭行为,不再拦截
});
winuiAppWindow.Closing += (sender, args) =>
{
// 拦截关闭
//args.Cancel = true;//注释后 不拦截窗口关闭,会调用 windows.OnClosed退出应用程序
// 隐藏窗口而不是销毁
winuiAppWindow.Hide();
};
隐藏窗口后怎么设置左键系统托盘是否居中 或者是否固定窗口显示位置
隐藏窗口后怎么设置左键系统托盘固定窗口的显示位置
WindowExtensions.Show = () =>
{
WindowExtensions.BringToFront();
////左键托盘是否居中
//var displyArea = DisplayArea.Primary;
//var scalingFactor = ((MauiWinUIWindow)Application.Current?.Windows[0].Handler.PlatformView)?.GetDisplayDensity() ?? 1;
//var width = 500 * scalingFactor;
//var height = 700 * scalingFactor;
//// 右键打开时窗口居中显示
//var centerX = (displyArea.WorkArea.Width - width) / 2;
//var centerY = (displyArea.WorkArea.Height - height) / 2;
//winuiAppWindow.MoveAndResize(new((int)centerX, (int)centerY, (int)width, (int)height), displyArea);
winuiAppWindow.Show();
};