Use shell module in rendering process (UI interface)
//Open in File Manager const { ..., shell } = require('electron'); const showFile = () => { if (!filePath) { return alert('This file has not been saved to the file system.'); } shell.showItemInFolder(filePath); }; //Open with default program const openInDefaultApplication = () => { if (!filePath) { return alert('This file has not been saved to the file system.'); } //electron-9.x no longer exists shell.openItem(fullPath) };
Use shell module in application menu
- applicationMenu.js
{ type: 'separator' }, { label: 'Show File', enabled: hasFilePath, click(item, focusedWindow) { if (!focusedWindow) { return dialog.showErrorBox( 'Cannot Show File\'s Location', 'There is currently no active document show.' ); } focusedWindow.webContents.send('show-file'); }, }, { label: 'Open in Default Application', enabled: hasFilePath, click(item, focusedWindow) { if (!focusedWindow) { return dialog.showErrorBox( 'Cannot Open File in Default Application', 'There is currently no active document to open.' ); } focusedWindow.webContents.send('open-in-default'); }, },
- renderer.js
ipcRenderer.on('show-file', showFile); ipcRenderer.on('open-in-default', openInDefaultApplication);
Use shell module in context menu
- renderer.js
//Context Menu const markdownContextMenu = Menu.buildFromTemplate([ ... { label: 'Show File in Folder', click: showFile, enabled: !!filePath }, { label: 'Open in Default', click: openInDefaultApplication, enabled: !!filePath }, { type: 'separator' }, ... ]); markdownView.addEventListener('contextmenu', (event) => { event.preventDefault(); markdownContextMenu.popup(); });
Disable Menu Items
!!
!! Often used to make type judgments, after the first step! (variable) do logical negation, in js novices often write bloated code like this:
Determines that variable a is not empty, undefined, or a non-empty string to execute the contents of a method body
var a; if(a!=null&&typeof(a)!=undefined&&a!=''){ //a Code executed with content }
In fact, we just need to write a judgment:
if(!!a){ //a Code to execute only if there is content... }
You can achieve the same effect as above.A is a variable with real meaning to execute the method, otherwise variables null, undefined, and''empty strings will not execute the following code.
Can be summarized;
"!"Is logic and operation, and can be logic with any variable and converted to a Boolean value, "!!" is the logic and inversion operation, especially the latter is concise and efficient in determining the type, eliminating redundant code to determine null, undefined and empty strings many times.
Dynamic Generation Menu
Disable menu: enabled:!! filePath
Dynamic startup menu: createContextMenu().popup();
const createContextMenu = () => { return Menu.buildFromTemplate([ { label: 'Open File', click() { mainProcess.getFileFromUser(); } }, { label: 'Show File in Folder', click: showFile, enabled: !!filePath }, { label: 'Open in Default', click: openInDefaultApplication, enabled: !!filePath }, { type: 'separator' }, { label: 'Cut', role: 'cut' }, { label: 'Copy', role: 'copy' }, { label: 'Paste', role: 'paste' }, { label: 'Select All', role: 'selectall' }, ]); }; markdownView.addEventListener('contextmenu', (event) => { event.preventDefault(); createContextMenu().popup(); });
Application Menu
What makes the application menu different from the context menu?
- Unlike the context menu, the application menu uses only one and is shared across all windows
- In a macOS system, even if the application does not have a window open.
- The application menu exists in the main process and does not have access to the rendering process variable (this variable is related to menu item disablement)
Create Application Menu (Dynamic Processing Enabled and Disabled)
Main points:
const hasOneOrMoreWindows = !!BrowserWindow.getAllWindows().length; //Is there a window open const focusedWindow = BrowserWindow.getFocusedWindow(); //Get the current focus window without returning null const hasFilePath = !!(focusedWindow && focusedWindow.getRepresentedFilename()); //focusedWindow.getRepresentedFilename() Return to the file opened by the window
focusedWindow.getRepresentedFilename() Only applicable to darwin platform
- applicationMenu.js
const { app, BrowserWindow, dialog, Menu } = require('electron'); const mainProcess = require('./main'); const createApplicationMenu = () => { const hasOneOrMoreWindows = !!BrowserWindow.getAllWindows().length; //Is there a window open const focusedWindow = BrowserWindow.getFocusedWindow(); //Get the current focus window without returning null const hasFilePath = !!(focusedWindow && focusedWindow.getRepresentedFilename()); //focusedWindow.getRepresentedFilename() Return to the file opened by the window const template = [ { label: 'File', submenu: [ ... { label: 'Save File', accelerator: 'CommandOrControl+S', enabled: hasOneOrMoreWindows, click(item, focusedWindow) { if (!focusedWindow) { return dialog.showErrorBox( 'Cannot Save or Export', 'There is currently no active document to save or export.' ); } focusedWindow.webContents.send('save-markdown'); }, }, { label: 'Export HTML', accelerator: 'Shift+CommandOrControl+S', enabled: hasOneOrMoreWindows, click(item, focusedWindow) { if (!focusedWindow) { return dialog.showErrorBox( 'Cannot Save or Export', 'There is currently no active document to save or export.' ); } focusedWindow.webContents.send('save-html'); }, }, { type: 'separator' }, { label: 'Show File', enabled: hasFilePath, click(item, focusedWindow) { if (!focusedWindow) { return dialog.showErrorBox( 'Cannot Show File\'s Location', 'There is currently no active document show.' ); } focusedWindow.webContents.send('show-file'); }, }, { label: 'Open in Default Application', enabled: hasFilePath, click(item, focusedWindow) { if (!focusedWindow) { return dialog.showErrorBox( 'Cannot Open File in Default Application', 'There is currently no active document to open.' ); } focusedWindow.webContents.send('open-in-default'); }, }, ], }, ... ]; ... return Menu.setApplicationMenu(Menu.buildFromTemplate(template)); }; module.exports = createApplicationMenu;
- main.js
When the program starts
app.on('ready', () => { //Menu.setApplicationMenu(applicationMenu); //Set application menu createApplicationMenu();//Set Application Menu mainWindow = createwindow(); });
When opening and closing a new window
newWindow.on('focus', () => { createApplicationMenu(); //Create a new application menu when the window gets focus }); newWindow.on('closed', () => { ... createApplicationMenu();//Create a new application menu when closing a window })
When opening a new file
const openFile = exports.openFile = (targetWindow, file) => { ... createApplicationMenu(); //Create a new application menu when opening a new file };