Xamarin Mac 如何实现点击窗口关闭按钮时最小化到托盘而非关闭?
点击窗口关闭按钮最小化到托盘实现方案
你要的Slack同款交互效果参考:
该功能的核心实现逻辑统一为:拦截窗口关闭事件,取消默认的销毁窗口/退出应用行为,将窗口隐藏/最小化,配合系统托盘图标实现入口留存,同时保留主动退出应用的入口避免应用无法正常关闭。
以下是常见开发技术栈的具体实现代码:
1. Electron(Slack本身基于该框架开发)
const { app, BrowserWindow, Tray, Menu, Notification } = require('electron') let mainWindow let tray let isAppQuitting = false // 标记是否是主动退出应用 // 初始化主窗口 function createMainWindow() { mainWindow = new BrowserWindow({ width: 900, height: 600, title: '你的应用名称' }) mainWindow.loadFile('index.html') // 监听全局退出事件,区分主动退出和点关闭按钮 app.on('before-quit', () => { isAppQuitting = true }) // 核心:拦截窗口关闭事件 mainWindow.on('close', (e) => { if (!isAppQuitting) { e.preventDefault() mainWindow.hide() // 可选:弹出系统通知提示用户 new Notification({ title: '应用已最小化', body: '可点击托盘图标重新打开窗口' }).show() } }) } // 初始化系统托盘 function initTray() { tray = new Tray('你的托盘图标本地路径.png') const trayMenu = Menu.buildFromTemplate([ { label: '打开主窗口', click: () => mainWindow.show() }, { label: '退出应用', click: () => app.quit() } ]) tray.setToolTip('你的应用名称') tray.setContextMenu(trayMenu) // 左键点击托盘直接打开窗口 tray.on('click', () => mainWindow.show()) } app.whenReady().then(() => { createMainWindow() initTray() })
2. C# WPF
using System.Windows; using System.Windows.Forms; using System.Drawing; public partial class MainWindow : Window { private NotifyIcon _trayIcon; private bool _isInitiativeExit = false; // 标记是否主动触发退出 public MainWindow() { InitializeComponent(); // 初始化托盘配置 _trayIcon = new NotifyIcon { Icon = new Icon("你的图标路径.ico"), Visible = true, Text = "你的应用名称" }; // 托盘右键菜单 var trayMenu = new ContextMenuStrip(); trayMenu.Items.Add("打开主窗口", null, (s, e) => ShowMainWindow()); trayMenu.Items.Add("退出应用", null, (s, e) => { _isInitiativeExit = true; Close(); }); _trayIcon.ContextMenuStrip = trayMenu; // 双击托盘打开窗口 _trayIcon.DoubleClick += (s, e) => ShowMainWindow(); } // 重写关闭事件拦截逻辑 protected override void OnClosing(System.ComponentModel.CancelEventArgs e) { base.OnClosing(e); if (!_isInitiativeExit) { e.Cancel = true; Hide(); } else { // 主动退出时销毁托盘资源 _trayIcon.Dispose(); } } private void ShowMainWindow() { Show(); WindowState = WindowState.Normal; Activate(); } }
3. Qt
// mainwindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QSystemTrayIcon> #include <QMenu> #include <QCloseEvent> class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr) : QMainWindow(parent) { // 初始化托盘 m_trayIcon = new QSystemTrayIcon(this); m_trayIcon->setIcon(QIcon(":/icons/tray_icon.png")); m_trayMenu = new QMenu(this); // 托盘菜单配置 m_trayMenu->addAction("打开主窗口", this, &MainWindow::showNormal); m_trayMenu->addAction("退出应用", qApp, &QApplication::quit); m_trayIcon->setContextMenu(m_trayMenu); m_trayIcon->show(); // 左键点击托盘切换窗口显隐 connect(m_trayIcon, &QSystemTrayIcon::activated, this, [this](QSystemTrayIcon::ActivationReason reason) { if (reason == QSystemTrayIcon::Trigger) { isVisible() ? hide() : showNormal(); } }); } protected: // 拦截关闭事件 void closeEvent(QCloseEvent *event) override { if (m_trayIcon->isVisible()) { hide(); event->ignore(); } } private: QSystemTrayIcon *m_trayIcon; QMenu *m_trayMenu; }; #endif // MAINWINDOW_H
内容的提问来源于stack exchange,提问作者Max951
相关产品推荐
相关产品推荐

