使用 Electron 自定义菜单
此系列文章的应用示例已发布于 GitHub: electron-api-demos-Zh_CN. 可以 Clone 或下载后运行查看. 欢迎 Star .
使用 Menu
和 MenuItem
模块可用于创建自定义本地菜单.
有两种菜单: 应用程序(顶部)菜单和上下文(右键单击)菜单.
在浏览器中打开 完整的 API 文档 .
创建应用程序菜单
支持: Win, macOS, Linux | 进程: Main
使用 Menu
和 MenuItem
模块可以自定义你的应用程序菜单. 如果没有设置任何菜单, Electron 将为您的应用默认生成一个最小的菜单.
此应用程序使用下面的代码设置应用程序菜单. 如果您点击应用程序菜单中的 "查看" 选项, 然后点击 "应用程序菜单演示", 则会显示一个信息框.
主进程
const electron = require('electron')
const BrowserWindow = electron.BrowserWindow
const Menu = electron.Menu
const app = electron.app
let template = [{
label: '编辑',
submenu: [{
label: '撤销',
accelerator: 'CmdOrCtrl+Z',
role: 'undo'
}, {
label: '重做',
accelerator: 'Shift+CmdOrCtrl+Z',
role: 'redo'
}, {
type: 'separator'
}, {
label: '剪切',
accelerator: 'CmdOrCtrl+X',
role: 'cut'
}, {
label: '复制',
accelerator: 'CmdOrCtrl+C',
role: 'copy'
}, {
label: '粘贴',
accelerator: 'CmdOrCtrl+V',
role: 'paste'
}, {
label: '全选',
accelerator: 'CmdOrCtrl+A',
role: 'selectall'
}]
}, {
label: '查看',
submenu: [{
label: '重载',
accelerator: 'CmdOrCtrl+R',
click: function (item, focusedWindow) {
if (focusedWindow) {
// 重载之后, 刷新并关闭所有的次要窗体
if (focusedWindow.id === 1) {
BrowserWindow.getAllWindows().forEach(function (win) {
if (win.id > 1) {
win.close()
}
})
}
focusedWindow.reload()
}
}
}, {
label: '切换全屏',
accelerator: (function () {
if (process.platform === 'darwin') {
return 'Ctrl+Command+F'
} else {
return 'F11'
}
})(),
click: function (item, focusedWindow) {
if (focusedWindow) {
focusedWindow.setFullScreen(!focusedWindow.isFullScreen())
}
}
}, {
label: '切换开发者工具',
accelerator: (function () {
if (process.platform === 'darwin') {
return 'Alt+Command+I'
} else {
return 'Ctrl+Shift+I'
}
})(),
click: function (item, focusedWindow) {
if (focusedWindow) {
focusedWindow.toggleDevTools()
}
}
}, {
type: 'separator'
}, {
label: '应用程序菜单演示',
click: function (item, focusedWindow) {
if (focusedWindow) {
const options = {
type: 'info',
title: '应用程序菜单演示',
buttons: ['好的'],
message: '此演示用于 "菜单" 部分, 展示如何在应用程序菜单中创建可点击的菜单项.'
}
electron.dialog.showMessageBox(focusedWindow, options, function () {})
}
}
}]
}, {
label: '窗口',
role: 'window',
submenu: [{
label: '最小化',
accelerator: 'CmdOrCtrl+M',
role: 'minimize'
}, {
label: '关闭',
accelerator: 'CmdOrCtrl+W',
role: 'close'
}, {
type: 'separator'
}, {
label: '重新打开窗口',
accelerator: 'CmdOrCtrl+Shift+T',
enabled: false,
key: 'reopenMenuItem',
click: function () {
app.emit('activate')
}
}]
}, {
label: '帮助',
role: 'help',
submenu: [{
label: '学习更多',
click: function () {
electron.shell.openExternal('http://electron.atom.io')
}
}]
}]
function addUpdateMenuItems (items, position) {
if (process.mas) return
const version = electron.app.getVersion()
let updateItems = [{
label: `Version ${version}`,
enabled: false
}, {
label: '正在检查更新',
enabled: false,
key: 'checkingForUpdate'
}, {
label: '检查更新',
visible: false,
key: 'checkForUpdate',
click: function () {
require('electron').autoUpdater.checkForUpdates()
}
}, {
label: '重启并安装更新',
enabled: true,
visible: false,
key: 'restartToUpdate',
click: function () {
require('electron').autoUpdater.quitAndInstall()
}
}]
items.splice.apply(items, [position, 0].concat(updateItems))
}
function findReopenMenuItem () {
const menu = Menu.getApplicationMenu()
if (!menu) return
let reopenMenuItem
menu.items.forEach(function (item) {
if (item.submenu) {
item.submenu.items.forEach(function (item) {
if (item.key === 'reopenMenuItem') {
reopenMenuItem = item
}
})
}
})
return reopenMenuItem
}
if (process.platform === 'darwin') {
const name = electron.app.getName()
template.unshift({
label: name,
submenu: [{
label: `关于 ${name}`,
role: 'about'
}, {
type: 'separator'
}, {
label: '服务',
role: 'services',
submenu: []
}, {
type: 'separator'
}, {
label: `隐藏 ${name}`,
accelerator: 'Command+H',
role: 'hide'
}, {
label: '隐藏其它',
accelerator: 'Command+Alt+H',
role: 'hideothers'
}, {
label: '显示全部',
role: 'unhide'
}, {
type: 'separator'
}, {
label: '退出',
accelerator: 'Command+Q',
click: function () {
app.quit()
}
}]
})
// 窗口菜单.
template[3].submenu.push({
type: 'separator'
}, {
label: '前置所有',
role: 'front'
})
addUpdateMenuItems(template[0].submenu, 1)
}
if (process.platform === 'win32') {
const helpMenu = template[template.length - 1].submenu
addUpdateMenuItems(helpMenu, 0)
}
app.on('ready', function () {
const menu = Menu.buildFromTemplate(template)
Menu.setApplicationMenu(menu)
})
app.on('browser-window-created', function () {
let reopenMenuItem = findReopenMenuItem()
if (reopenMenuItem) reopenMenuItem.enabled = false
})
app.on('window-all-closed', function () {
let reopenMenuItem = findReopenMenuItem()
if (reopenMenuItem) reopenMenuItem.enabled = true
})
高级技巧
了解操作系统菜单的差异.
在为多个操作系统设计应用程序时, 请务必注意应用程序菜单在每个操作系统上的不同约定之处。
例如, 在 Windows 上, 加速器设置为 &
. 命名约定也有所不同, 如 "设置" 或 "首选项". 下面是学习操作系统特定标准的资源:
创建上下文菜单
支持: Win, macOS, Linux | 进程: Main
可以使用 Menu
和 MenuItem
模块创建上下文或右键单击菜单. 您可以右键单击此应用程序中的任何位置, 或单击示例按钮以查看示例上下文菜单.
在这个示例中, 我们使用 ipcRenderer
模块来展示从渲染器进程显式调用它时的上下文菜单.
有关所有可用的属性请查看 上下文菜单事件文档 .
主进程
const electron = require('electron')
const BrowserWindow = electron.BrowserWindow
const Menu = electron.Menu
const MenuItem = electron.MenuItem
const ipc = electron.ipcMain
const app = electron.app
const menu = new Menu()
menu.append(new MenuItem({ label: 'Hello' }))
menu.append(new MenuItem({ type: 'separator' }))
menu.append(new MenuItem({ label: 'Electron', type: 'checkbox', checked: true }))
app.on('browser-window-created', function (event, win) {
win.webContents.on('context-menu', function (e, params) {
menu.popup(win, params.x, params.y)
})
})
ipc.on('show-context-menu', function (event) {
const win = BrowserWindow.fromWebContents(event.sender)
menu.popup(win)
})
渲染器进程
const ipc = require('electron').ipcRenderer
// 告诉主进程在单击示例按钮时显示菜单
const contextMenuBtn = document.getElementById('context-menu')
contextMenuBtn.addEventListener('click', function () {
ipc.send('show-context-menu')
})
如果这边文章对您有帮助, 感谢 下方点赞 或 Star GitHub: electron-api-demos-Zh_CN 支持, 谢谢.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。