上下文菜单
¥Context Menu
上下文菜单是右键单击应用界面某处(或按下快捷键,例如 Windows 上的 Shift + F10)时出现的弹出菜单。
¥Context menus are pop-up menus that appear when right-clicking (or pressing a shortcut such as Shift + F10 on Windows) somewhere in an app's interface.
Electron 默认不会显示上下文菜单。但是,可以通过在 Menu 类的实例上使用 menu.popup
函数来创建上下文菜单。你需要监听特定的上下文菜单事件,并手动设置 menu.popup
的触发器。
¥No context menu will appear by default in Electron. However, context menus can be created by using
the menu.popup
function on an instance of the
Menu class. You will need to listen for specific context menu events and set up
the trigger for menu.popup
manually.
在 Electron 中,有两种监听上下文菜单事件的方法:通过 webContents 在主进程中执行,或通过 contextmenu
Web 事件在渲染进程中执行。
¥There are two ways of listening for context menu events in Electron: either via the main process
through webContents or in the renderer process via the
contextmenu
web event.
使用 context-menu
事件(主事件)
¥Using the context-menu
event (main)
每当在特定 WebContents
实例的边界内检测到右键单击时,就会触发 context-menu
事件。传递给监听器的 params
对象提供了一个详尽的属性列表,用于区分接收事件的元素类型。
¥Whenever a right-click is detected within the bounds of a specific WebContents
instance, a
context-menu
event is triggered. The params
object
passed to the listener provides an extensive list of attributes to distinguish which type of element
is receiving the event.
例如,如果你想为链接提供上下文菜单,请检查 linkURL
参数。如果你想检查可编辑元素(例如 <textarea/>
),请检查 isEditable
参数。
¥For example, if you want to provide a context menu for links, check for the linkURL
parameter.
If you want to check for editable elements such as <textarea/>
, check for the isEditable
parameter.
- 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://developer.mozilla.org/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
事件(渲染器)
¥Using the contextmenu
event (renderer)
或者,你也可以在渲染进程中监听 DOM 元素上的 contextmenu
事件,并通过进程间通信 (IPC) 调用 menu.popup
函数。
¥Alternatively, you can also listen to the contextmenu
event available on DOM elements in the renderer process and call the menu.popup
function via IPC.
[!TIP] 要了解有关 Electron 中 IPC 基础知识的更多信息,请参阅 进程间通信 指南。
¥[!TIP] To learn more about IPC basics in Electron, see the Inter-Process Communication guide.
- 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://developer.mozilla.org/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 菜单项(例如:写作工具)
¥Additional macOS menu items (e.g. Writing Tools)
在 macOS 上,Electron 的上下文菜单默认禁用 编写工具、AutoFill 和 服务 菜单项。要启用这些功能,请将与目标 webContents
关联的 Web 框架主 传递给 menu.popup
中的 frame
参数。
¥On macOS, the Writing Tools,
AutoFill, and
Services menu items
are disabled by default for context menus in Electron. To enable these features, pass the
WebFrameMain associated to the target webContents
to the frame
parameter in menu.popup
.
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
})
}
})