Created
January 11, 2022 17:16
-
-
Save VerteDinde/4d85af0c3d4479ca629b23e9ce7576b6 to your computer and use it in GitHub Desktop.
context-menu-demo
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="UTF-8" /> | |
<title>Customize Menus</title> | |
</head> | |
<body> | |
<div> | |
<h1>Customize Menus</h1> | |
<h3> | |
The <code>Menu</code> and <code>MenuItem</code> modules can be used to | |
create custom native menus. | |
</h3> | |
<p> | |
There are two kinds of menus: the application (top) menu and context | |
(right-click) menu. | |
</p> | |
<p> | |
Open the | |
<a href="https://electronjs.org/docs/api/menu" | |
>full API documentation<span | |
>(opens in new window)</span | |
></a | |
> | |
in your browser. | |
</p> | |
</div> | |
<div> | |
<h2>Create an application menu</h2> | |
<div> | |
<div> | |
<p> | |
The <code>Menu</code> and <code>MenuItem</code> modules allow you to | |
customize your application menu. If you don't set any menu, Electron | |
will generate a minimal menu for your app by default. | |
</p> | |
<p> | |
If you click the 'View' option in the application menu and then the | |
'App Menu Demo', you'll see an information box displayed. | |
</p> | |
<div> | |
<h2>ProTip</h2> | |
<strong>Know operating system menu differences.</strong> | |
<p> | |
When designing an app for multiple operating systems it's | |
important to be mindful of the ways application menu conventions | |
differ on each operating system. | |
</p> | |
<p> | |
For instance, on Windows, accelerators are set with an | |
<code>&</code>. Naming conventions also vary, like between | |
"Settings" or "Preferences". Below are resources for learning | |
operating system specific standards. | |
</p> | |
<ul> | |
<li> | |
<a | |
href="https://developer.apple.com/macos/human-interface-guidelines/menus/menu-anatomy/" | |
>macOS<span | |
>(opens in new window)</span | |
></a | |
> | |
</li> | |
<li> | |
<a | |
href="https://msdn.microsoft.com/en-us/library/windows/desktop/bb226797(v=vs.85).aspx" | |
>Windows<span | |
>(opens in new window)</span | |
></a | |
> | |
</li> | |
<li> | |
<a | |
href="https://developer.gnome.org/hig/stable/menu-bars.html.en" | |
>Linux<span | |
>(opens in new window)</span | |
></a | |
> | |
</li> | |
</ul> | |
</div> | |
</div> | |
</div> | |
</div> | |
<div> | |
<h2>Create a context menu</h2> | |
<div> | |
<div> | |
<div> | |
<button id="context-menu">View Demo</button> | |
</div> | |
<p> | |
A context, or right-click, menu can be created with the | |
<code>Menu</code> and <code>MenuItem</code> modules as well. You can | |
right-click anywhere in this app or click the demo button to see an | |
example context menu. | |
</p> | |
<p> | |
In this demo we use the <code>ipcRenderer</code> module to show the | |
context menu when explicitly calling it from the renderer process. | |
</p> | |
<p> | |
See the full | |
<a | |
href="https://electronjs.org/docs/api/web-contents/#event-context-menu" | |
>context-menu event documentation</a | |
> | |
for all the available properties. | |
</p> | |
</div> | |
</div> | |
</div> | |
<script> | |
// You can also require other files to run in this process | |
require("./renderer.js"); | |
</script> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Modules to control application life and create native browser window | |
const { | |
BrowserWindow, | |
Menu, | |
MenuItem, | |
ipcMain, | |
app, | |
shell, | |
dialog | |
} = require('electron') | |
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 }) | |
) | |
const template = [ | |
{ | |
label: 'Edit', | |
submenu: [ | |
{ | |
label: 'Undo', | |
accelerator: 'CmdOrCtrl+Z', | |
role: 'undo' | |
}, | |
{ | |
label: 'Redo', | |
accelerator: 'Shift+CmdOrCtrl+Z', | |
role: 'redo' | |
}, | |
{ | |
type: 'separator' | |
}, | |
{ | |
label: 'Cut', | |
accelerator: 'CmdOrCtrl+X', | |
role: 'cut' | |
}, | |
{ | |
label: 'Copy', | |
accelerator: 'CmdOrCtrl+C', | |
role: 'copy' | |
}, | |
{ | |
label: 'Paste', | |
accelerator: 'CmdOrCtrl+V', | |
role: 'paste' | |
}, | |
{ | |
label: 'Select All', | |
accelerator: 'CmdOrCtrl+A', | |
role: 'selectall' | |
} | |
] | |
}, | |
{ | |
label: 'View', | |
submenu: [ | |
{ | |
label: 'Reload', | |
accelerator: 'CmdOrCtrl+R', | |
click: (item, focusedWindow) => { | |
if (focusedWindow) { | |
// on reload, start fresh and close any old | |
// open secondary windows | |
if (focusedWindow.id === 1) { | |
BrowserWindow.getAllWindows().forEach(win => { | |
if (win.id > 1) win.close() | |
}) | |
} | |
focusedWindow.reload() | |
} | |
} | |
}, | |
{ | |
label: 'Toggle Full Screen', | |
accelerator: (() => { | |
if (process.platform === 'darwin') { | |
return 'Ctrl+Command+F' | |
} else { | |
return 'F11' | |
} | |
})(), | |
click: (item, focusedWindow) => { | |
if (focusedWindow) { | |
focusedWindow.setFullScreen(!focusedWindow.isFullScreen()) | |
} | |
} | |
}, | |
{ | |
label: 'Toggle Developer Tools', | |
accelerator: (() => { | |
if (process.platform === 'darwin') { | |
return 'Alt+Command+I' | |
} else { | |
return 'Ctrl+Shift+I' | |
} | |
})(), | |
click: (item, focusedWindow) => { | |
if (focusedWindow) { | |
focusedWindow.toggleDevTools() | |
} | |
} | |
}, | |
{ | |
type: 'separator' | |
}, | |
{ | |
label: 'App Menu Demo', | |
click: function (item, focusedWindow) { | |
if (focusedWindow) { | |
const options = { | |
type: 'info', | |
title: 'Application Menu Demo', | |
buttons: ['Ok'], | |
message: | |
'This demo is for the Menu section, showing how to create a clickable menu item in the application menu.' | |
} | |
dialog.showMessageBox(focusedWindow, options, function () {}) | |
} | |
} | |
} | |
] | |
}, | |
{ | |
label: 'Window', | |
role: 'window', | |
submenu: [ | |
{ | |
label: 'Minimize', | |
accelerator: 'CmdOrCtrl+M', | |
role: 'minimize' | |
}, | |
{ | |
label: 'Close', | |
accelerator: 'CmdOrCtrl+W', | |
role: 'close' | |
}, | |
{ | |
type: 'separator' | |
}, | |
{ | |
label: 'Reopen Window', | |
accelerator: 'CmdOrCtrl+Shift+T', | |
enabled: false, | |
key: 'reopenMenuItem', | |
click: () => { | |
app.emit('activate') | |
} | |
} | |
] | |
}, | |
{ | |
label: 'Help', | |
role: 'help', | |
submenu: [ | |
{ | |
label: 'Learn More', | |
click: () => { | |
shell.openExternal('https://electronjs.org') | |
} | |
} | |
] | |
} | |
] | |
function addUpdateMenuItems (items, position) { | |
if (process.mas) return | |
const version = app.getVersion() | |
const updateItems = [ | |
{ | |
label: `Version ${version}`, | |
enabled: false | |
}, | |
{ | |
label: 'Checking for Update', | |
enabled: false, | |
key: 'checkingForUpdate' | |
}, | |
{ | |
label: 'Check for Update', | |
visible: false, | |
key: 'checkForUpdate', | |
click: () => { | |
require('electron').autoUpdater.checkForUpdates() | |
} | |
}, | |
{ | |
label: 'Restart and Install Update', | |
enabled: true, | |
visible: false, | |
key: 'restartToUpdate', | |
click: () => { | |
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(item => { | |
if (item.submenu) { | |
item.submenu.items.forEach(item => { | |
if (item.key === 'reopenMenuItem') { | |
reopenMenuItem = item | |
} | |
}) | |
} | |
}) | |
return reopenMenuItem | |
} | |
if (process.platform === 'darwin') { | |
const name = app.getName() | |
template.unshift({ | |
label: name, | |
submenu: [ | |
{ | |
label: `About ${name}`, | |
role: 'about' | |
}, | |
{ | |
type: 'separator' | |
}, | |
{ | |
label: 'Services', | |
role: 'services', | |
submenu: [] | |
}, | |
{ | |
type: 'separator' | |
}, | |
{ | |
label: `Hide ${name}`, | |
accelerator: 'Command+H', | |
role: 'hide' | |
}, | |
{ | |
label: 'Hide Others', | |
accelerator: 'Command+Alt+H', | |
role: 'hideothers' | |
}, | |
{ | |
label: 'Show All', | |
role: 'unhide' | |
}, | |
{ | |
type: 'separator' | |
}, | |
{ | |
label: 'Quit', | |
accelerator: 'Command+Q', | |
click: () => { | |
app.quit() | |
} | |
} | |
] | |
}) | |
// Window menu. | |
template[3].submenu.push( | |
{ | |
type: 'separator' | |
}, | |
{ | |
label: 'Bring All to Front', | |
role: 'front' | |
} | |
) | |
addUpdateMenuItems(template[0].submenu, 1) | |
} | |
if (process.platform === 'win32') { | |
const helpMenu = template[template.length - 1].submenu | |
addUpdateMenuItems(helpMenu, 0) | |
} | |
// Keep a global reference of the window object, if you don't, the window will | |
// be closed automatically when the JavaScript object is garbage collected. | |
let mainWindow | |
function createWindow () { | |
// Create the browser window. | |
mainWindow = new BrowserWindow({ | |
width: 800, | |
height: 600, | |
webPreferences: { | |
nodeIntegration: true | |
} | |
}) | |
// and load the index.html of the app. | |
mainWindow.loadFile('index.html') | |
// Open the DevTools. | |
// mainWindow.webContents.openDevTools() | |
// Emitted when the window is closed. | |
mainWindow.on('closed', function () { | |
// Dereference the window object, usually you would store windows | |
// in an array if your app supports multi windows, this is the time | |
// when you should delete the corresponding element. | |
mainWindow = null | |
}) | |
} | |
// This method will be called when Electron has finished | |
// initialization and is ready to create browser windows. | |
// Some APIs can only be used after this event occurs. | |
app.whenReady().then(() => { | |
createWindow() | |
const menu = Menu.buildFromTemplate(template) | |
Menu.setApplicationMenu(menu) | |
}) | |
// Quit when all windows are closed. | |
app.on('window-all-closed', function () { | |
// On macOS it is common for applications and their menu bar | |
// to stay active until the user quits explicitly with Cmd + Q | |
const reopenMenuItem = findReopenMenuItem() | |
if (reopenMenuItem) reopenMenuItem.enabled = true | |
if (process.platform !== 'darwin') { | |
app.quit() | |
} | |
}) | |
app.on('activate', function () { | |
// On macOS it is common to re-create a window in the app when the | |
// dock icon is clicked and there are no other windows open. | |
if (mainWindow === null) { | |
createWindow() | |
} | |
}) | |
app.on('browser-window-created', (event, win) => { | |
const reopenMenuItem = findReopenMenuItem() | |
if (reopenMenuItem) reopenMenuItem.enabled = false | |
win.webContents.on('context-menu', (e, params) => { | |
e.sender; | |
console.log('e.sender:', e.sender); | |
menu.popup(win, params.x, params.y) | |
}) | |
}) | |
ipcMain.on('show-context-menu', event => { | |
const win = BrowserWindow.fromWebContents(event.sender) | |
menu.popup(win) | |
}) | |
// In this file you can include the rest of your app's specific main process | |
// code. You can also put them in separate files and require them here. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "smooth-mine-led-sej3b", | |
"productName": "smooth-mine-led-sej3b", | |
"description": "My Electron application description", | |
"keywords": [], | |
"main": "./main.js", | |
"version": "1.0.0", | |
"author": "khammond", | |
"scripts": { | |
"start": "electron ." | |
}, | |
"dependencies": {}, | |
"devDependencies": { | |
"electron": "16.0.5" | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const { ipcRenderer } = require('electron') | |
// Tell main process to show the menu when demo button is clicked | |
const contextMenuBtn = document.getElementById('context-menu') | |
contextMenuBtn.addEventListener('click', () => { | |
ipcRenderer.send('show-context-menu') | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment