Electron Native
Electron is powerful because it not only allows you to write frontend code, but also access native system features such as menus, dialogs, tray icons, notifications, and global shortcuts.\\n\\nIn this chapter, we'll see how to call these features through main process modules.\\n\\n* * *\\n\\n## Menu System\\n\\nElectron provides the `Menu` module for creating menu bars, context menus, and system tray menus.\\n\\n### Application Menu (Menu)\\n\\nThe application menu is the menu bar displayed at the top of the window (macOS) or within the application window.\\n\\n## Example\\n\\nconst{ app, Menu }= require('electron')\\n\\nconst template =[\\n\\n{\\n\\n label:'Files',\\n\\n submenu:[\\n\\n{ label:'New File', accelerator:'CmdOrCtrl+N', click:()=> console.log('New File')},\\n\\n{ label:'Open...', accelerator:'CmdOrCtrl+O'},\\n\\n{ type:'separator'},\\n\\n{ label:'Exit', role:'quit'}\\n\\n]\\n\\n},\\n\\n{\\n\\n label:'Edit',\\n\\n submenu:[\\n\\n{ role:'undo'},\\n\\n{ role:'redo'},\\n\\n{ type:'separator'},\\n\\n{ role:'cut'},\\n\\n{ role:'copy'},\\n\\n{ role:'paste'}\\n\\n]\\n\\n}\\n\\n]\\n\\nconst menu = Menu.buildFromTemplate(template)\\n\\n Menu.setApplicationMenu(menu)\\n\\n**Description:**\\n\\n* `label`: Menu title.\\n* `submenu`: Submenu array.\\n* `accelerator`: Keyboard shortcut (cross-platform syntax `CmdOrCtrl+X` for macOS and Windows).\\n* `role`: System predefined behaviors, such as `quit`, `copy`, `paste`.\\n* `click`: Click event callback function.\\n\\n### Context Menu\\n\\nRight-click menus are typically triggered in the renderer process:\\n\\n## Example\\n\\n// main.js\\n\\nconst{ ipcMain, Menu }= require('electron')\\n\\nipcMain.on('show-context-menu',(event)=>{\\n\\nconst menu = Menu.buildFromTemplate([\\n\\n{ label:'Refresh', click:()=> event.sender.reload()},\\n\\n{ label:'Copy', role:'copy'},\\n\\n{ label:'Paste', role:'paste'}\\n\\n])\\n\\n menu.popup()\\n\\n})\\n\\n## Example\\n\\n// renderer.js\\n\\n window.addEventListener('contextmenu',(e)=>{\\n\\n e.preventDefault()\\n\\n window.electronAPI.showContextMenu()\\n\\n})\\n\\n### System Tray Menu\\n\\nDisplay icons and menus in the system notification area.\\n\\n## Example\\n\\nconst{ Tray, Menu, nativeImage }= require('electron')\\n\\n let tray =null\\n\\nfunction createTray(){\\n\\nconst icon = nativeImage.createFromPath('icon.png')\\n\\n tray =new Tray(icon)\\n\\nconst contextMenu = Menu.buildFromTemplate([\\n\\n{ label:'Open Main Window', click:()=> mainWindow.show()},\\n\\n{ label:'Exit', click:()=> app.quit()}\\n\\n])\\n\\n tray.setToolTip('My Electron App')\\n\\n tray.setContextMenu(contextMenu)\\n\\n}\\n\\n### Menu Shortcuts\\n\\nDefined via `accelerator`. For example:\\n\\n{ label: 'Save', accelerator: 'CmdOrCtrl+S', click: saveFile }\\n* `CmdOrCtrl`: Automatically adapts to macOS/Windows.\\n* `Alt+F4`: Close window on Windows.\\n* `Cmd+Q`: Quit application on macOS.\\n\\n* * *\\n\\n## System Dialogs\\n\\nThe `dialog` module provides native system dialogs for files, messages, errors, etc.\\n\\n### File/Folder Selection\\n\\nconst { dialog } = require('electron') async function openFileDialog() { const result = await dialog.showOpenDialog({ title: 'Select File', properties: ['openFile', 'multiSelections'], filters: [{ name: 'Text File', extensions: ['txt', 'md'] }] }) console.log(result.filePaths)}\\n### Save Dialog\\n\\nasync function saveFileDialog() { const result = await dialog.showSaveDialog({ title: 'SaveFiles', defaultPath: 'New Document.txt' }) console.log(result.filePath)}\\n### Message/Error Dialogs\\n\\ndialog.showMessageBox({ type: 'info', title: 'Tips', message: 'Operation Completed!'}) dialog.showErrorBox('Errors', 'FilesSaveFailed, please try again.')\\n\\n* * *\\n\\n## System Tray\\n\\nThe Tray allows applications to run in the background while still being accessible through a system icon.\\n\\n### Creating Tray Icon\\n\\nconst { Tray } = require('electron')const path = require('path')let tray = new Tray(path.join(__dirname, 'trayIcon.png'))\\n### Tray Menu and Tooltip\\n\\nconst contextMenu = Menu.buildFromTemplate([ { label: 'Show Window', click: () => mainWindow.show() }, { label: 'Exit', click: () => app.quit() }]) tray.setToolTip('Electron App Running') tray.setContextMenu(contextMenu)\\n### Tray Notification\\n\\ntray.displayBalloon({ icon: path.join(__dirname, 'icon.png'), title: 'New Message', content: 'You have a new Notification'})\\n### Minimize to Tray\\n\\nListen for close event to hide window:\\n\\nmainWindow.on('close', (event) => { event.preventDefault() mainWindow.hide()})\\n\\n* * *\\n\\n## Notifications\\n\\nElectron's `Notification` class can display system notifications across platforms.\\n\\n### Sending System Notifications\\n\\nnew Notification({ title: 'Task Completed', body: 'Your files have been downloaded'}).show()\\n### Notification Interaction Handling\\n\\nconst notif = new Notification({ title: 'Click Notification', body: 'Click Me to Trigger Event' }) notif.on('click', () => { console.log('User clicked the Notification')}) notif.show()\\n### Cross-Platform Compatibility\\n\\n* Supported on macOS, Windows, and Linux;\\n* macOS requires enabling "notification permissions";\\n* Linux typically requires system support for `libnotify`.\\n\\n* * *\\n\\n## Global Shortcuts\\n\\nRegister system-level hotkeys through `globalShortcut`.\\n\\n### Registering Global Shortcuts\\n\\nconst { globalShortcut } = require('electron') app.whenReady().then(() => { globalShortcut.register('CmdOrCtrl+Shift+I', () => { console.log('Shortcut TriggeredοΌOpenDebug Tools') mainWindow.webContents.openDevTools() })})\\n### Shortcut Conflict Handling\\n\\nCheck before registering:\\n\\nif (globalShortcut.isRegistered('CmdOrCtrl+Shift+I')) { console.log('Shortcut Already in Use')}\\n### Platform Differences Handling\\n\\nUse conditional checks:\\n\\nconst shortcut = process.platform === 'darwin' ? 'Cmd+Shift+T' : 'Ctrl+Shift+T' globalShortcut.register(shortcut, () => console.log('Shortcut Triggered'))\\n\\n* * *\\n\\n## Summary\\n\\n| Feature | Module | Typical Use |\\n| --- | --- | --- |\\n| Menu | `Menu` | Application menu, context menu, tray menu |\\n| Dialog | `dialog` | Open files, save files, show info or errors |\\n| Tray | `Tray` | Background running, system status display |\\n| Notification | `Notification` | Notify user of event progress, system alerts |\\n| Global Shortcut | `globalShortcut` | Register system-level shortcut operations |\\n\\n* * *\\n\\n## Electron Native Features Demo Project\\n\\n### Project Structure\\n\\nmy-electron-native-demo/βββ package.json βββ main.js # Main process logicβββ preload.js # Preload script (secure communication)βββ index.html # Main interface\\n### package.json\\n\\nNote: Do not write comments in JSON files (otherwise EJSONPARSE error will occur)\\n\\n{ "name": "my-electron-native-demo", "version": "1.0.0", "description": "Electron Native Feature DemoProject", "main": "main.js", "scripts": { "start": "electron ." }, "devDependencies": { "electron": "latest" }}\\nInstall dependencies:\\n\\nnpm install\\nStart application:\\n\\nnpm start\\n### main.js (Main Process)\\n\\n## Example\\n\\nconst{ app, BrowserWindow, Menu, Tray, dialog, Notification, globalShortcut, ipcMain }= require('electron')\\n\\nconst path = require('path')\\n\\nlet mainWindow, tray\\n\\nfunction createWindow(){\\n\\n mainWindow =new BrowserWindow({\\n\\n width:900,\\n\\n height:600,\\n\\n webPreferences:{\\n\\n preload: path.join(__dirname,'preload.js')\\n\\n}\\n\\n})\\n\\nmainWindow.loadFile('index.html')\\n\\n// Show after page load complete\\n\\n mainWindow.once('ready-to-show',()=> mainWindow.show())\\n\\n// Listen for window close: minimize to tray\\n\\n mainWindow.on('close',(event)=>{\\n\\n event.preventDefault()\\n\\n mainWindow.hide()\\n\\n})\\n\\n}\\n\\nfunction createMenu(){\\n\\nconst template =[\\n\\n{\\n\\n label:'Files',\\n\\n submenu:[\\n\\n{ label:'OpenFiles', click: openFile },\\n\\n{ label:'SaveFiles', click: saveFile },\\n\\n{ type:'separator'},\\n\\n{ label:'Exit', click:()=> app.quit()}\\n\\n]\\n\\n},\\n\\n{\\n\\n label:'Tools',\\n\\n submenu:[\\n\\n{ label:'Show Notification', click: showNotification },\\n\\n{ label:'About', click: showAbout }\\n\\n]\\n\\n}\\n\\n]\\n\\nconst menu = Menu.buildFromTemplate(template)\\n\\n Menu.setApplicationMenu(menu)\\n\\n}\\n\\nfunction createTray(){\\n\\nconst icon = path.join(__dirname,'icon.png')// Please prepare a 16x16 or 32x32 icon\\n\\n tray =new Tray(icon)\\n\\nconst contextMenu = Menu.buildFromTemplate([\\n\\n{ label:'Show Window', click:()=> mainWindow.show()},\\n\\n{ label:'Exit', click:()=> app.quit()}\\n\\n])\\n\\n tray.setToolTip('Electron Native Feature Demo')\\n\\n tray.setContextMenu(contextMenu)\\n\\n}\\n\\nfunction registerShortcuts(){\\n\\n globalShortcut.register('CmdOrCtrl+Shift+I',()=>{\\n\\n mainWindow.webContents.openDevTools()\\n\\n})\\n\\n}\\n\\nasync function openFile(){\\n\\nconst result = await dialog.showOpenDialog({\\n\\n properties:['openFile'],\\n\\n filters:[{ name:'Text File', extensions:['txt','md']}]\\n\\n})\\n\\nif(!result.canceled&& result.filePaths.length>0){\\n\\n mainWindow.webContents.send('file-opened', result.filePaths)\\n\\n}\\n\\n}\\n\\nasync function saveFile(){\\n\\nconst result = await dialog.showSaveDialog({\\n\\n title:'SaveFiles',\\n\\n defaultPath:'New Document.txt'\\n\\n})\\n\\nif(!result.canceled){\\n\\n dialog.showMessageBox({ type:'info', message: `FilesSetSavetoοΌ${result.filePath}` })\\n\\n}\\n\\n}\\n\\nfunction showNotification(){\\n\\nconst notif =new Notification({\\n\\n title:'Electron Notification',\\n\\n body:'This is a system Notification!'\\n\\n})\\n\\n notif.on('click',()=>{\\n\\n dialog.showMessageBox({ message:'You clicked the Notification!'})\\n\\n})\\n\\n notif.show()\\n\\n}\\n\\nfunction showAbout(){\\n\\n dialog.showMessageBox({\\n\\n type:'info',\\n\\n title:'About',\\n\\n message:'Electron Native Feature Demo Project Version: 1.0.0'\\n\\n})\\n\\n}\\n\\n// Renderer process calls\\n\\n ipcMain.handle('show-dialog', async ()=>{\\n\\nconst result = await dialog.showMessageBox({\\n\\n type:'info',\\n\\n title:'From Main Process',\\n\\n message:'This is a dialog from the main process!'\\n\\n})\\n\\nreturn result.response\\n\\n})\\n\\n// Lifecycle\\n\\n app.whenReady().then(()=>{\\n\\n createWindow()\\n\\n createMenu()\\n\\n createTray()\\n\\n registerShortcuts()\\n\\n})\\n\\napp.on('window-all-closed',()=>{\\n\\nif(process.platform!=='darwin') app.quit()\\n\\n})\\n\\n### preload.js (Secure Bridge)\\n\\n## Example\\n\\nconst{ contextBridge, ipcRenderer }= require('electron')\\n\\ncontextBridge.exposeInMainWorld('electronAPI',{\\n\\n showDialog:()=> ipcRenderer.invoke('show-dialog')\\n\\n})\\n\\n### index.html (Frontend Interface)\\n\\n## Example\\n\\nElectron Native Feature Demo \\n\\n body { font-family: sans-serif; text-align: center; margin-top: 80px; }\\n\\n button { padding: 10px 20px; margin: 10px; font-size: 16px; cursor: pointer; }\\n\\n #filePath { color: #666; f
YouTip