上下文菜单
上下文菜单是在应用程序界面中的某个位置右键单击(或按下诸如 Windows 上的 Shift + F10 之类的快捷键)时出现的弹出菜单。
默认情况下,Electron 中不会出现上下文菜单。但是,可以使用 menu.popup 函数在 Menu 类的实例上创建上下文菜单。您需要监听特定的上下文菜单事件并手动设置 menu.popup 的触发器。
在 Electron 中监听上下文菜单事件有两种方法:一种是通过 webContents 在主进程中进行监听,另一种是在渲染进程中通过 contextmenu web 事件进行监听。
使用 context-menu 事件 (主进程)
每当在特定 WebContents 实例的范围内检测到右键单击时,就会触发一个 context-menu 事件。传递给监听器的 params 对象提供了大量的属性来区分接收事件的元素类型。
例如,如果您想为链接提供上下文菜单,请检查 linkURL 参数。如果您想检查可编辑元素,例如 <textarea/>,请检查 isEditable 参数。
- main.js
- index.html
const { app, BrowserWindow, Menu } = require('electron/main')
function createWindow () {
const win = new BrowserWindow()
const menu = Menu.buildFromTemplate([
{ role: 'copy' },
{ role: 'cut' },
{ role: 'paste' },
{ role: 'selectall' }
])
win.webContents.on('context-menu', (_event, params) => {
// only show the context menu if the element is editable
if (params.isEditable) {
menu.popup()
}
})
win.loadFile('index.html')
}
app.whenReady().then(() => {
createWindow()
app.on('activate', function () {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- https://mdn.org.cn/en-US/docs/Web/HTTP/CSP -->
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
<title>Context Menu Demo</title>
</head>
<body>
<h1>Context Menu Demo</h1>
<textarea></textarea>
</body>
</html>
使用 contextmenu 事件 (渲染进程)
或者,您还可以监听渲染进程中 DOM 元素上可用的 contextmenu 事件,并通过 IPC 调用 menu.popup 函数。
提示
要了解有关 Electron 中 IPC 基本知识的更多信息,请参阅 进程间通信 指南。
- main.js
- preload.js
- index.html
// Modules to control application life and create native browser window
const { app, BrowserWindow, ipcMain, Menu } = require('electron/main')
const path = require('node:path')
function createWindow () {
const mainWindow = new BrowserWindow({
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})
mainWindow.loadFile('index.html')
const menu = Menu.buildFromTemplate([
{ role: 'copy' },
{ role: 'cut' },
{ role: 'paste' },
{ role: 'selectall' }
])
ipcMain.on('context-menu', (event) => {
menu.popup({
window: BrowserWindow.fromWebContents(event.sender)
})
})
}
app.whenReady().then(() => {
createWindow()
app.on('activate', function () {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})
const { ipcRenderer } = require('electron/renderer')
document.addEventListener('DOMContentLoaded', () => {
const textarea = document.getElementById('editable')
textarea.addEventListener('contextmenu', (event) => {
event.preventDefault()
ipcRenderer.send('context-menu')
})
})
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- https://mdn.org.cn/en-US/docs/Web/HTTP/CSP -->
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
<title>Context Menu Demo</title>
</head>
<body>
<h1>Context Menu Demo</h1>
<textarea id="editable"></textarea>
</body>
</html>
额外的 macOS 菜单项(例如,写作工具)
在 macOS 上,写作工具、自动填充 和 服务 菜单项默认情况下在 Electron 的上下文菜单中被禁用。要启用这些功能,请将与目标 webContents 关联的 WebFrameMain 传递给 menu.popup 中的 frame 参数。
将框架与上下文菜单关联
const { BrowserWindow, Menu } = require('electron/main')
const menu = Menu.buildFromTemplate([{ role: 'editMenu' }])
const win = new BrowserWindow()
win.webContents.on('context-menu', (_event, params) => {
// Whether the context is editable.
if (params.isEditable) {
menu.popup({
frame: params.frame
})
}
})