07.《Electron 跨平台开发实战》- chapter07-应用菜单、上下文菜单

应用菜单

替换设置应用程序菜单

  • 创建应用菜单模块
    创建一个新的名为application-menu.js文件,
const { app, BrowseWindow, Menu, shell } = require('electron');
const mainProcess = require('./main');

//创建数组模板,它描述了整个菜单的完整结构
const template = [
    {
        label: 'Edit',
        submenu: [
            {
                label: '复制',
                accelerator: 'CommandOrControl+C', //accelerator属性定义键盘快捷键
                role: 'copy'
            },
            {
                label: '粘贴',
                accelerator: 'CommandOrControl+V', //accelerator属性定义键盘快捷键
                role: 'paste'
            }
        ]
    }
];
//macOS系统:总是将第一个菜单作为应用菜单,故将Edit菜单及其以后的菜单都往后移一个位置
if (process.platform === 'darwin') {
    const name = 'Fire Sale';
    template.unshift({ label: name }); //向数组的开头添加一个或更多元素,并返回新的长度
}

//https://www.cnblogs.com/fayin/p/6831071.html
module.exports = Menu.buildFromTemplate(template);
  • main.js 已入并设置应用菜单
const {..., Menu } = require('electron');
const applicationMenu = require('./application-menu'); //引入应用菜单模块
...
app.on('ready', () => {
    Menu.setApplicationMenu(applicationMenu); //设置应用菜单
    mainWindow = createwindow();
});

知识点

module.exports = Menu.buildFromTemplate(template);

macOS系统:总是将第一个菜单作为应用菜单,故将Edit菜单及其以后的菜单都往后移一个位置

菜单项的role 属性

每一种role属性都关联到一种操作系统内置的功能,有如下值:

  • undo
  • redo
  • cut
  • copy
  • paste
  • selectall
  • minimize
  • close

补上macOS系统的应用菜单

大部分macOS应用都具备的应用菜单功能,electron为macOS系统提供一组额外的role

if (process.platform === 'darwin') {
  const name = 'Firesale';
  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 ${name}`,
        accelerator: 'Command+Q',
        click() { app.quit(); }, // A
      },
    ],
  });

知识点

 #### 自定义菜单项的点击事件: { label:xxx, click() { app.quit(); }}  
 #### 菜单项分割线  { type: 'separator' }

Window role

仅在macOS系统中用 Window role,会在菜单的末尾添加一个包含当前应用所有窗口的列表

不支持 Window role 的系统自动略过
窗口的最大化,最小化,关闭等

 {
    label: 'Window',
    submenu: [
      {
        label: 'Minimize',
        accelerator: 'CommandOrControl+M',
        role: 'minimize',
      },
      {
        label: 'Close',
        accelerator: 'CommandOrControl+W',
        role: 'close',
      },
    ],
  },

...
  //为macOS系统中用Window role
  const windowMenu = template.find(item => item.label === 'Window'); // B
  windowMenu.role = 'window';
  windowMenu.submenu.push(
    { type: 'separator' },
    {
      label: 'Bring All to Front',
      role: 'front',
    }
  );

help菜单

  • 大部分macOS系统使用这个功能,按下 command+shift+?, 用户就可以使用这个菜单搜索功能
  • 一般可以在help菜单中添加打开开发者工具
 {
    label: 'Help',
    role: 'help',
    submenu: [
      {
        label: 'Visit Website',
        click() { /* To be implemented */ }
      },
      {
        label: 'Toggle Developer Tools',
        click(item, focusedWindow) {
          if (focusedWindow) focusedWindow.webContents.toggleDevTools();
        }
      }
    ]
  }

特有的功能菜单

New File、Open File、Save File、Export Html

  • applicatoinMenu.js
{
        label: 'File',
        submenu: [
            {
                label: 'New File',
                accelerator: 'CommandOrControl+N',
                click() {
                    mainProcess.createWindow();
                }
            },
            {
                label: 'Open File',
                accelerator: 'CommandOrControl+O',
                click(item, focusedWindow) {
                    if (focusedWindow) {
                        return mainProcess.getFileFromUser(focusedWindow);
                    }

                    const newWindow = mainProcess.createWindow();

                    newWindow.on('show', () => {
                        mainProcess.getFileFromUser(newWindow);
                    });
                },
            },
            {
                label: 'Save File',
                accelerator: 'CommandOrControl+S',
                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',
                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');
                },
            },
        ],
    },
  • renderer.js
ipcRenderer.on('save-markdown', () => {
  mainProcess.saveMarkdown(currentWindow, filePath, markdownView.value);
});

ipcRenderer.on('save-html', () => {
  mainProcess.saveHtml(currentWindow, htmlView.innerHTML);
});

上下文菜单

const markdownContextMenu = Menu.buildFromTemplate([{},{}])->markdownContextMenu.popup();

  • renderer.js
const { remote, ...} = require('electron');
const { Menu } = remote;
...
//上下文菜单
const markdownContextMenu = Menu.buildFromTemplate([
    { label: 'Open File', click() { mainProcess.getFileFromUser(); } },
    { 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();
    markdownContextMenu.popup();
});

原文地址:https://www.cnblogs.com/easy5weikai/p/13138861.html