应用菜单
要创建自定义菜单,你需要使用 Electron
的 Menu
模块。下面是个例子:
const { app, BrowserWindow, Menu } = require('electron')
// 创建菜单模板
const myMenus = [
{
label: '文件',
submenu: [
{
label: '打开',
accelerator: 'CmdOrCtrl+O', // 快捷键
click() {
// 处理打开操作
}
},
{
label: '保存',
accelerator: 'CmdOrCtrl+S',
click() {
// 处理保存操作
}
},
{
type: 'separator' // 添加分隔线
},
{
label: '退出',
accelerator: 'CmdOrCtrl+Q',
click() {
app.quit(); // 退出应用程序
}
}
]
},
{
label: '编辑',
submenu: [
{ role: 'undo' },
{ role: 'redo' },
{ type: 'separator' },
{ role: 'cut' },
{ role: 'copy' },
{ role: 'paste' },
{ role: 'pasteAndMatchStyle' },
{ role: 'delete' },
{ role: 'selectAll' }
]
}
];
// 创建菜单
const menu = Menu.buildFromTemplate(myMenus);
// 将菜单设置为应用程序的菜单
Menu.setApplicationMenu(menu)
app.on('ready', () => {
const win = new BrowserWindow({ width: 800, height: 600 })
})
当涉及 Electron 的 Menu
模块时,以下是一些主要的知识点:
- 创建菜单:使用
Menu.buildFromTemplate(template)
方法可以根据提供的菜单模板创建菜单对象。菜单模板是一个包含菜单项的数组,每个菜单项都有自己的属性,如标签(label)、快捷键(accelerator)、角色(role)和点击事件(click)等。 - 设置应用程序菜单:使用
Menu.setApplicationMenu(menu)
方法可以将菜单设置为应用程序的菜单。通过调用这个方法,你可以在应用程序的菜单栏或窗口中显示自定义的菜单。 菜单项属性:
label
:菜单项显示的文本。accelerator
:为菜单项指定快捷键,允许用户使用键盘快速访问菜单项。click
:菜单项被点击时触发的回调函数。role
:使用内置的角色来指定一些常见操作的行为,如复制('copy')、剪切('cut')、粘贴('paste')等。这些角色会根据操作系统的约定自动处理相应的操作。submenu
:指定一个子菜单,允许创建层级嵌套的菜单。
- 分隔线和标签:通过在菜单模板中使用
type: 'separator'
可以添加分隔线,用于在菜单中分隔不同的菜单项。你还可以使用type: 'label'
来创建一个标签,它是一个不可点击的文本项,用于在菜单中提供额外的说明或分组。 - 上下文菜单:除了应用程序菜单,你还可以创建上下文菜单(也称为右键菜单)。通过监听特定的事件(如
contextmenu
),可以在合适的时候显示自定义的上下文菜单。
菜单项和role相关的信息可以参考:https://www.electronjs.org/zh/docs/latest/api/menu-item
右键菜单
自定义右键菜单和自定义应用菜单用法基本差不多,也是通过Menu
模块实现的。由于右键菜单的显示一般发生在渲染进程中,所有我们需要使用进程间通信和预处理脚本。下面是一个例子:
// 主进程 main.js
const { app, BrowserWindow, Menu, ipcMain } = require('electron')
const path = require('path')
// 1.创建菜单模板
const myMenus = [
{
label: '菜单1',
accelerator: 'CmdOrCtrl+O', // 快捷键
click() {
// 处理打开操作
}
},
{
label: '菜单2',
submenu: [
{ role: 'undo' },
{ role: 'redo' },
{ type: 'separator' },
{ role: 'cut' },
{ role: 'copy' },
{ role: 'paste' },
{ role: 'delete' },
{ role: 'selectAll' }
]
}
];
// 2.创建菜单
const menu = Menu.buildFromTemplate(myMenus);
app.on('ready', () => {
// 创建窗口
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'p1.js')
}
})
win.loadFile('index.html')
// 监听子进程的showContextMenu频道
ipcMain.on('showContextMenu', function () {
// 3.在窗口中显示右键菜单
menu.popup()
})
})
// 预处理脚本文件 p1.js
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('elecAPI', {
showContextMenu: function () {
// 向主进程showContextMenu频道发送信息
ipcRenderer.send('showContextMenu')
}
})
<!-- 渲染进程中的代码 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>您好,世界</title>
</head>
<body>
<h1>您好,世界!</h1>
<script>
document.addEventListener('contextmenu', function () {
// 调用在预处理脚本中定义的函数,想法主进程发送信息
elecAPI.showContextMenu()
})
</script>
</body>
</html>