0Pricing
Electron Desktop App Development · 课时

原生菜单与上下文菜单

实现自定义应用菜单、上下文菜单和托盘菜单,为用户提供熟悉的导航方式与选项

原生菜单与上下文菜单 是 CoddyKit 上的免费 Electron Desktop App Development 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Electron Desktop App Development 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Electron Desktop App Development 课程共包含 4 节课。

本课时的部分内容尚未翻译,以英文显示。

Native Menus in Electron

Electron lets you build desktop apps using web technologies. But desktop apps also need native features like menus!

Native menus offer a familiar experience to users, fitting seamlessly into their operating system. Electron's Menu module allows you to create these.

  • Application Menus: The main menu bar (File, Edit, View).
  • Context Menus: Right-click menus specific to an element.
  • Tray Menus: Menus for icons in the system tray or dock.

Building the Main Menu Bar

The Application Menu is the main menu bar at the top of your app window (Windows/Linux) or the top of the screen (macOS).

It usually contains standard options like "File", "Edit", "View", and "Help". These menus make your app feel native and provide essential navigation.

You define its structure using a JavaScript array of objects, called a menu template.

Code: Basic Application Menu

Let's create a minimal application menu. This code snippet goes into your Electron app's main.js file.

It defines a "File" menu with an "Exit" option that quits the app. (Note: nodeIntegration: true, contextIsolation: false are used here for simplicity in examples, but often require more secure configurations for production apps).

const { app, BrowserWindow, Menu } = require('electron');

let mainWindow;

function createWindow () {
  mainWindow = new BrowserWindow({
    width: 400,
    height: 300,
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: false
    }
  });

  mainWindow.loadFile('index.html'); // Ensure you have an index.html file

  const template = [
    {
      label: 'File',
      submenu: [
        {
          label: 'Exit',
          accelerator: 'CmdOrCtrl+Q',
          click() { app.quit(); }
        }
      ]
    }
  ];

  const menu = Menu.buildFromTemplate(template);
  Menu.setApplicationMenu(menu);

  mainWindow.on('closed', () => { mainWindow = null; });
}

app.whenReady().then(createWindow);

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit();
});

app.on('activate', () => {
  if (mainWindow === null) createWindow();
});

Advanced Menu Items & Roles

Menu items can have special roles that provide standard functionality (like 'copy', 'paste', 'quit') and ensure platform-specific behavior.

You can also create nested menus (submenus) to organize options better. Accelerators (keyboard shortcuts) can be added for quick access.

  • role: 'quit': Quits the app.
  • role: 'separator': Adds a dividing line.
  • accelerator: 'CmdOrCtrl+Z': Defines a keyboard shortcut.

Code: Full Application Menu

Let's enhance our application menu. We'll add an "Edit" menu with standard roles and a "Help" menu with a custom item.

Notice how roles simplify common actions, and submenus keep the main menu clean.

const { app, BrowserWindow, Menu } = require('electron');

let mainWindow;

function createWindow () {
  mainWindow = new BrowserWindow({
    width: 400,
    height: 300,
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: false
    }
  });

  mainWindow.loadFile('index.html');

  const template = [
    {
      label: 'File',
      submenu: [
        { label: 'New', accelerator: 'CmdOrCtrl+N' },
        { type: 'separator' },
        { label: 'Exit', role: 'quit' }
      ]
    },
    {
      label: 'Edit',
      submenu: [
        { label: 'Undo', role: 'undo' },
        { label: 'Redo', role: 'redo' },
        { type: 'separator' },
        { label: 'Cut', role: 'cut' },
        { label: 'Copy', role: 'copy' },
        { label: 'Paste', role: 'paste' }
      ]
    },
    {
      label: 'Help',
      submenu: [
        { label: 'About App', click() { console.log('About clicked!'); } }
      ]
    }
  ];

  const menu = Menu.buildFromTemplate(template);
  Menu.setApplicationMenu(menu);

  mainWindow.on('closed', () => { mainWindow = null; });
}

app.whenReady().then(createWindow);

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit();
});

app.on('activate', () => {
  if (mainWindow === null) createWindow();
});

Dynamic Context Menus

Context menus are those "right-click" menus that appear when you interact with specific elements or areas of an application.

Unlike the static application menu, context menus are often dynamic, changing based on what you've clicked on. They're built using the same Menu module.

They are typically created in the main process and then displayed (popped up) from the renderer process via Inter-Process Communication (IPC).

Code: Creating a Context Menu

Here's how to define a simple context menu. For this example, we'll demonstrate it being popped up from the main process after a delay for simplicity. In a real app, it's usually triggered by a right-click event in the renderer process, communicating with the main process.

The popup() method displays the menu.

const { app, BrowserWindow, Menu } = require('electron');

let mainWindow;

function createWindow () {
  mainWindow = new BrowserWindow({
    width: 400,
    height: 300,
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: false
    }
  });

  mainWindow.loadFile('index.html');

  const contextMenuTemplate = [
    { label: 'Inspect Element', click() { mainWindow.webContents.openDevTools(); } },
    { type: 'separator' },
    { label: 'Reload Page', role: 'reload' }
  ];

  const contextMenu = Menu.buildFromTemplate(contextMenuTemplate);

  // For demonstration: show context menu after a delay
  setTimeout(() => {
    contextMenu.popup({ window: mainWindow });
    console.log('Context menu popped up!');
  }, 3000);

  mainWindow.on('closed', () => { mainWindow = null; });
}

app.whenReady().then(createWindow);

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit();
});

app.on('activate', () => {
  if (mainWindow === null) createWindow();
});

System Tray & Dock Menus

A tray icon (also known as a status bar icon on macOS or system tray icon on Windows/Linux) allows your application to run in the background and provide quick access to common actions.

The Tray module in Electron lets you create these icons and attach a tray menu to them, which appears when the user interacts with the icon (e.g., right-click).

Code: Basic Tray Menu

This example shows how to create a simple tray icon with a context menu. Remember to provide a small icon file (e.g., icon.png) in your project root.

The tray icon will appear in your system's notification area or dock. Clicking the tray icon will toggle the main window's visibility.

const { app, BrowserWindow, Menu, Tray } = require('electron');
const path = require('path');

let mainWindow;
let tray;

function createWindow () {
  mainWindow = new BrowserWindow({
    width: 400,
    height: 300,
    show: false, // Start hidden for tray app
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: false
    }
  });

  mainWindow.loadFile('index.html');

  mainWindow.on('closed', () => { mainWindow = null; });
}

app.whenReady().then(() => {
  createWindow();

  // Path to your icon file (e.g., in the same directory as main.js)
  const iconPath = path.join(__dirname, 'icon.png'); 
  tray = new Tray(iconPath);

  const contextMenu = Menu.buildFromTemplate([
    { label: 'Open App', click: () => { mainWindow.show(); } },
    { label: 'Toggle DevTools', click: () => { mainWindow.webContents.toggleDevTools(); } },
    { type: 'separator' },
    { label: 'Quit', click: () => { app.quit(); } }
  ]);

  tray.setToolTip('My Electron Tray App');
  tray.setContextMenu(contextMenu);

  tray.on('click', () => {
    mainWindow.isVisible() ? mainWindow.hide() : mainWindow.show();
  });
});

app.on('before-quit', () => {
  // Clean up tray icon before quitting to prevent memory leaks
  if (tray) tray.destroy();
});

app.on('activate', () => {
  // On macOS it's common to re-create a window in the app when the dock icon is clicked
  if (mainWindow === null) createWindow();
});

// For apps with tray icons, you might not want to quit when all windows are closed
// app.on('window-all-closed', () => {
//   if (process.platform !== 'darwin') app.quit(); 
// });

Menu Types Check

You've learned about different types of native menus in Electron.

Which of the following statements about Electron menus is TRUE?

Menus: Key Takeaways

Well done! You've learned how to integrate native menus into your Electron applications.

  • Use the Menu module to create application, context, and tray menus.
  • Define menu structures using menu templates (arrays of objects).
  • Leverage menu item roles for standard functionality and platform consistency.
  • Application menus are for the main window bar, context menus for dynamic right-click options, and tray menus for system tray/dock icons.
  • Always use Menu.buildFromTemplate() and Menu.setApplicationMenu() for the main app menu.

These native touches greatly improve the user experience of your desktop app!

常见问题解答

「原生菜单与上下文菜单」课时是免费的吗?

是的 — 「原生菜单与上下文菜单」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Electron Desktop App Development 课程的其余内容,请升级到 CoddyKit PRO。 Electron Desktop App Development 课程共包含 4 节课。

「原生菜单与上下文菜单」这节课中我会学到什么?

实现自定义应用菜单、上下文菜单和托盘菜单,为用户提供熟悉的导航方式与选项 你通过在浏览器中直接运行的动手代码来练习 Electron Desktop App Development,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Electron Desktop App Development 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Electron Desktop App Development 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。

「原生菜单与上下文菜单」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Electron Desktop App Development 课中编写并运行代码吗?

能。每节 Electron Desktop App Development 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 原生菜单与上下文菜单
  2. 对话框与通知
  3. Shell 集成
  4. 全局快捷键与剪贴板访问
← 返回 Electron Desktop App Development