跳转到主要内容

托盘菜单

本指南将指导您完成创建系统托盘中具有自己的上下文菜单的图标的过程。

  • 在 macOS 上,图标将位于屏幕右上角的 菜单栏扩展区域。
  • 在 Windows 上,图标将位于任务栏末端的 通知区域
  • 在 Linux 上,托盘的位置将根据您的桌面环境而有所不同。

创建托盘图标

您的 Electron 应用程序的托盘图标需要通过 Tray 类的实例以编程方式创建。该类构造函数需要一个 NativeImage 实例或指向兼容图标文件的路径。

注意

文件格式因操作系统而异。有关更多详细信息,请参阅 Tray API 文档的 平台注意事项 部分。

最小化到托盘

为了在所有窗口都关闭时保持应用程序和系统托盘图标的活动状态,您需要在 app 模块上有一个 window-all-closed 事件的监听器。Electron 的基础模板通常会监听此事件,但在 Windows 和 Linux 上会退出应用程序以模拟标准的操作系统行为。

设置最小化到托盘
app.on('window-all-closed', () => {
// having this listener active will prevent the app from quitting.
})

附加上下文菜单

您可以将一个 Menu 实例传递给 tray.setContextMenu 函数,来将上下文菜单附加到 Tray 对象。

注意

与常规 上下文菜单 不同,托盘上下文菜单不需要使用 menu.popup API 手动进行集成。相反,Tray 对象会为您处理点击事件(尽管 API 上存在各种与点击相关的事件,用于高级用例)。

创建可以退出应用程序的托盘菜单
const { nativeImage } = require('electron/common')
const { app, Tray, Menu } = require('electron/main')

// save a reference to the Tray object globally to avoid garbage collection
let tray

// 16x16 red circle data URL
const icon = nativeImage.createFromDataURL('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAACTSURBVHgBpZKBCYAgEEV/TeAIjuIIbdQIuUGt0CS1gW1iZ2jIVaTnhw+Cvs8/OYDJA4Y8kR3ZR2/kmazxJbpUEfQ/Dm/UG7wVwHkjlQdMFfDdJMFaACebnjJGyDWgcnZu1/lrCrl6NCoEHJBrDwEr5NrT6ko/UV8xdLAC2N49mlc5CylpYh8wCwqrvbBGLoKGvz8Bfq0QPWEUo/EAAAAASUVORK5CYII=')

// The Tray can only be instantiated after the 'ready' event is fired
app.whenReady().then(() => {
tray = new Tray(icon)
const contextMenu = Menu.buildFromTemplate([
{ role: 'quit' }
])
tray.setContextMenu(contextMenu)
})
提示

要了解有关在 Electron 中创建菜单的更多信息,请参阅 菜单 指南。

警告

在 macOS 的托盘顶层菜单项中,enabledvisibility 属性不可用。

可运行的 Fiddle 演示

以下是一个可运行的示例,其中向 Tray 的上下文菜单添加了各种菜单项,以帮助控制应用程序状态并与 Tray API 本身进行交互。

const { app, BrowserWindow, Menu, Tray } = require('electron/main')
const { nativeImage } = require('electron/common')

// save a reference to the Tray object globally to avoid garbage collection
let tray = null

function createWindow () {
const mainWindow = new BrowserWindow()
mainWindow.loadFile('index.html')
}

// The Tray object can only be instantiated after the 'ready' event is fired
app.whenReady().then(() => {
createWindow()

const red = nativeImage.createFromDataURL('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAACTSURBVHgBpZKBCYAgEEV/TeAIjuIIbdQIuUGt0CS1gW1iZ2jIVaTnhw+Cvs8/OYDJA4Y8kR3ZR2/kmazxJbpUEfQ/Dm/UG7wVwHkjlQdMFfDdJMFaACebnjJGyDWgcnZu1/lrCrl6NCoEHJBrDwEr5NrT6ko/UV8xdLAC2N49mlc5CylpYh8wCwqrvbBGLoKGvz8Bfq0QPWEUo/EAAAAASUVORK5CYII=')
const green = nativeImage.createFromDataURL('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAACOSURBVHgBpZLRDYAgEEOrEzgCozCCGzkCbKArOIlugJvgoRAUNcLRpvGH19TkgFQWkqIohhK8UEaKwKcsOg/+WR1vX+AlA74u6q4FqgCOSzwsGHCwbKliAF89Cv89tWmOT4VaVMoVbOBrdQUz+FrD6XItzh4LzYB1HFJ9yrEkZ4l+wvcid9pTssh4UKbPd+4vED2Nd54iAAAAAElFTkSuQmCC')

tray = new Tray(red)
tray.setToolTip('Tray Icon Demo')

const contextMenu = Menu.buildFromTemplate([
{
label: 'Open App',
click: () => {
const wins = BrowserWindow.getAllWindows()
if (wins.length === 0) {
createWindow()
} else {
wins[0].focus()
}
}
},
{
label: 'Set Green Icon',
type: 'checkbox',
click: ({ checked }) => {
checked ? tray.setImage(green) : tray.setImage(red)
}
},
{
label: 'Set Title',
type: 'checkbox',
click: ({ checked }) => {
checked ? tray.setTitle('Title') : tray.setTitle('')
}
},
{ role: 'quit' }
])

tray.setContextMenu(contextMenu)
})

app.on('window-all-closed', function () {
// This will prevent the app from closing when windows close
})

app.on('activate', function () {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})