【问题标题】:How to create a contextMenu (right-click menu) using contextBridge in Electron如何在 Electron 中使用 contextBridge 创建 contextMenu(右键菜单)
【发布时间】:2020-12-05 23:43:56
【问题描述】:

问题

你好,我是电子初学者。

我知道使用contextBridge 是在 Electron 中制作安全应用的好方法。 我想在contextBridge中实现一个contextMenu(右键菜单)来指定Renderer进程中的Main进程要做什么进程,但是我做不到。

你能给我一些建议吗?

我的代码

ma​​in.js(主进程)(部分初始化)

function createWindow() {
  mainWindow = new BrowserWindow({
    width: 960,
    height: 540,
    webPreferences: {
      nodeIntegration: false,
      contextIsolation: true,
      enableRemoteModule: false,
      preload: __dirname + "/preload.js"
    }
  });
  mainWindow.loadFile(__dirname + "/index.html");
}

preload.js

const contextBridge = require("electron");
const remote = require("electron").remote;
const Menu =remote.Menu;
const MenuItem=remote.MenuItem;

contextBridge.exposeInMainWorld(
  "api", {
    menu:()=>{
      const menu = new Menu();

      // label definition
      menu.append(new MenuItem({
        label: 'MenuItem1',
        click() {
          console.log('item 1 clicked');
        }
      }));

      // right clicked
      window.addEventListener('contextmenu', (e) => {
        e.preventDefault();
        menu.popup({
          window: remote.getCurrentWindow()
        });
      }, false);
    }
  }
);

index.html(渲染器进程)

<!DOCTYPE html>

<html>

<head>
  <script>
    window.api.menu();
  </script>
</head>

<body>
</body>

</html>



我尝试了什么

一开始,这是失败的。

仅将main.js 中的webreferences 更改为nodeIntegration:true(不使用contextBridge)并将preload.jsmenu 放入&lt;script&gt;index.html,我可以实现contextMenu

但是我知道这种方式不能制作安全的应用程序,因为没有使用contextBridge

ma​​in.js

function createWindow() {
  mainWindow = new BrowserWindow({
    width: 960,
    height: 540,
    webPreferences: {
      nodeIntegration: true // changing false to true, deleting the others
    }
  });
  mainWindow.loadFile(__dirname + "/index.html");
}

preload.js
没有变化(因为没有加载)

index.html

<!DOCTYPE html>

<html>

<head>
  <script>
    // add the following
    const remote = require("electron").remote;
    const Menu =remote.Menu;
    const MenuItem=remote.MenuItem;

    const menu = new Menu();

    // label definition
    menu.append(new MenuItem({
      label: 'MenuItem1',
      click() {
        console.log('item 1 clicked');
      }
    }));

    // right cliced
    window.addEventListener('contextmenu', (e) => {
      e.preventDefault();
      menu.popup({
        window: remote.getCurrentWindow()
      });
    }, false);
  </script>
</head>

<body>
</body>

</html>



感谢您阅读到最后。

【问题讨论】:

    标签: electron


    【解决方案1】:

    我相信您的上下文菜单将不起作用,因为您在预加载后尝试在预加载器中构建它。您需要在 main.js 文件中构建菜单。

    这是我使用的方法。

    像这样设置你的 preloader.js:

    // whitelist channels
    let validChannels = ["load-context-menu", "pop-context-menu"];
    
    contextBridge.exposeInMainWorld(
        "electron",
        {
            on: (channel, callback) => {
                //console.log('Channel: ' + channel);
                if (validChannels.includes(channel)) {
                    ipcRenderer.on(channel, callback);
                }
            },
            sendSync: (channel, data) => {
                //console.log('Channel: ' + channel);
                if (validChannels.includes(channel)) {
                    return ipcRenderer.sendSync(channel, data);
                }
            }
        }
    );
    

    然后这样称呼它:

    window.electron.sendSync('load-context-menu', null);
    window.electron.sendSync('pop-context-menu', null);
    

    最后,将这个添加到你的 main.js 文件中:

    const editorContextMenuBuilder = require('./scripts/editorContextMenuBuilder');
    let contextMenu;
    
    ipcMain.on('load-context-menu', (event, arg) => {
      try {
        contextMenu = editorContextMenuBuilder();
        event.returnValue = true;
      } catch (err) {
        event.returnValue = 'LOAD CONTEXT ERROR';
      }
    });
    ipcMain.on('pop-context-menu', (event, arg) => {
      try{
        contextMenu.popup();
        event.returnValue = true;
      } catch (err) {
        event.returnValue = 'POP CONTEXT ERROR';
      }
    });
    

    如果您需要向菜单生成器发送数据,请在发送之前将对象字符串化,然后使用 JSON 在 main.js 中将其解析回。

    【讨论】:

      猜你喜欢
      • 2021-08-07
      • 1970-01-01
      • 1970-01-01
      • 2011-07-20
      • 2021-04-03
      • 2010-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多