コンテキストメニュー
コンテキストメニューとは、アプリのインターフェイスのどこかを右クリックすると (または Windows では Shift + F10 などのショートカットを押すと) 表示されるポップアップメニューです。
Electron ではコンテキストメニューはデフォルトで表示されません。 しかし、Menu クラスのインスタンスに menu.popup 関数を使用してコンテキストメニューを作成できます。 特定のコンテキストメニューのイベントをリッスンし、menu.popup のトリガを手動で設定する必要があります。
Electron でコンテキストメニューのイベントをリッスンする方法は 2 つあります。メインプロセスで webContents を介してリッスンする方法と、レンダラープロセスで contextmenu ウェブイベントを介してリッスンする方法です。
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://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 イベント (レンダラー) を使用する
あるいは、レンダラープロセス内の 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://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 メニューアイテム (作文ツールなど)
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) => {
// コンテキストが編集可能かどうか。
if (params.isEditable) {
menu.popup({
frame: params.frame
})
}
})