context menu of electron

Electron

Electron 默认是没有右键支持的,右键点击也不会有效果。为了能够提供一些右键的行为,需要在合适的时间点,手动构造菜单并显示出来。

这里对右键点击的判断,如果放在 render 层用 JavaScript 去监听 contextmenu 事件,虽然可以从 event.target 上拿到元素,但是要判断当前选择的位置、能否选择/黏贴、是否有拼写错误的单词等,都比较困难,很容易写出问题来。

Electron 暴露了 Chromium 的数据,在 WebContents 中增加了 context-menu 的事件。在这个事件的回调函数中,提供了很多的数据,能够帮助更好的了解当前的右键点击状态,从而更好地显示右键菜单项。

context-menu 的文档见这里

这个功能提交的 Pull Request 见 #5379

context-menu 的回调函数中,第二个参数提供了非常多有用的数据,比如:

  • selectionText - 选中的文字
  • misspelledWord - 当前的拼写错误单词(如果没有拼写错误,这里的返回是空字符串)
  • editFlags - 包含了 canCut, canCopy, canPaste, canSelectAll 等各式布尔值,用于表示当前右键的位置是否允许剪切/复制/黏贴/全选等操作。完整的列表可以参考文档

一个例子:

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

const webContents = remote.getCurrentWebContents();

function buildMenuFromSuggestions(suggestions) {
  if (suggestions.length === 0) return [];
  return suggestions.map(function (suggestion) {
    return {
      label: suggestion,
      click: function () {
        webContents.replaceMisspelling(suggestion);
      },
    };
  }).concat([
    { type: 'separator' },
  ]);
}

webContents.on('context-menu', (event, info) => {
  const { canCut, canCopy, canPaste, canSelectAll } = info.editFlags;
  const { misspelledWord } = info;

  // use your own function of `getCorrections`
  const suggestions = getCorrections(misspelledWord);

  const menuConfig = buildMenuFromSuggestions(suggestions)
    .concat([
      { label: 'Cut', role: 'cut', enabled: canCut },
      { label: 'Copy', role: 'copy', enabled: canCopy },
      { label: 'Paste', role: 'paste', enabled: canPaste },
      {
        label: 'Select All',
        enabled: canSelectAll,
        // role: 'selectAll'
        // following shows an example of how to manually call the API
        click: webContents.selectAll,
      },
    ]);
  
  const menu = remote.Menu.buildFromTemplate(menuConfig);
  menu.popup(remote.getCurrentWindow());
});