电子中2个浏览器窗口之间的通信

时间:2016-10-25 23:34:45

标签: webbrowser-control ipc electron

我需要构建一个跨越多个监视器屏幕的应用程序,如下所示: enter image description here 电子支持多个窗口,但如何在它们之间进行通信?

4 个答案:

答案 0 :(得分:7)

要记住的主要事情是,在Electron中,interProcess通信由ipcMain(在主进程中)和ipcRenderer(在所有创建的窗口中)完成。如下所示: enter image description here 根据我在GitHub评论中看到的内容 - 不允许在Renderer实例之间进行直接通信。一切都必须通过mainProcess。

代码: 的 mainProcess.js:

function createWindow1 () {
  window1 = new BrowserWindow({width: 800,height: 600})
  window1.loadURL(`file://${__dirname}/window1.html`)
  window1.webContents.openDevTools()
  window1.on('closed', function () {
     window1 = null
  })
  return window1
}
function createWindow2 () {
  window2 = new BrowserWindow({width: 1000, height: 600})
  window2.loadURL(`file://${__dirname}/window2.html`)
  window2.webContents.openDevTools()
  window2.on('closed', function () {
    window2 = null
  })
  return window2
}

app.on('ready', () => {
  window1 = createWindow1();
  window2 = createWindow2();

  ipcMain.on('nameMsg', (event, arg) => {
  console.log("name inside main process is: ", arg); // this comes form within window 1 -> and into the mainProcess
  event.sender.send('nameReply', { not_right: false }) // sends back/replies to window 1 - "event" is a reference to this chanel.
  window2.webContents.send( 'forWin2', arg ); // sends the stuff from Window1 to Window2.
});

<强> window1.html:

<body>
    <input type="text" id="name" value="" placeholder="Enter your name">
    <button type="button" id="sendName" >Send the name! </button>
</body>
<script>
   // You can also require other files to run in this process
   require('./window1.js')
</script>

<强> window1.js:

const ipcRenderer = require('electron').ipcRenderer

let name = document.getElementById('name');

ButtonSendName = document.getElementById('sendName');
ButtonSendName.addEventListener('click', (event) => {
  ipcRenderer.send('nameMsg', name.value);
})

ipcRenderer.on('nameReply', (event, arg) => {
  console.log(arg) // why/what is not right..
});

window2.html:

<body>
  <p id = "showName"></p>
</body>

<script>
  require('./window2.js')
</script>

<强> window2.js:

const { ipcRenderer } = require('electron')

showName = document.getElementById('showName')
ipcRenderer.on('forWin2', function (event, arg){
  console.log(arg);
  showName.innerHTML = arg;
});
console.log("I'm Window2");

演示会更好,但我不知道如何构建电子CodeBin应用程序。这张图片给你一个想法: enter image description here

享受Electron的力量!

答案 1 :(得分:0)

根据您的要求,可以创建SharedWorker,它充当在Windows之间传输MessagePort的代理。注意:SharedWorker要求所有窗口都从同一来源运行(可能不符合您的要求)。因此,例如,在主窗口中创建一个MessageChannel(具有两个端口),然后将端口1通过SharedWorker传输到一个窗口,将端口2传输到另一个窗口。现在,两个窗口可以使用postMessage通过端口直接通信。作为奖励,postMessage还支持可转换。我当时正在研究这个想法,但尚未完全开发该库,但是您可以从此处进行的一些工作中获得这个想法:https://github.com/lneir/electron-direct-comm

答案 2 :(得分:0)

每当我们谈到在Electron应用程序中从一个窗口到另一个窗口进行通信时,您总是想着IPC系统,即进程间通信。

因此,在一个窗口中,您将监听一个事件,例如表单提交。

提交表单后,您可以从输入中删除文本并将事件发送到Electron应用程序。

然后,Electron应用将触发其自己的事件,并将事件继续发送到mainWindow,后者将接收文本并将其附加到其列表中。

您可以在辅助window.html文件中仅使用原始JavaScript来开始,如下所示:

  document.querySelector('form').addEventListener('submit', event => {
    event.preventDefault();
  });

因此,以上假设您正在使用要提交的表单。

答案 3 :(得分:0)

编辑:我为此创建了一个存储库:electron-multi-monitorenter image description here

我们的项目遇到了类似的问题。然而,两个 BrowserWindows 都必须来回传递 JS 对象和函数。

通过 IPC 调用提出的解决方案是我们尝试的第一件事,但还不够。当您只需要传递几个小对象但很快就会达到它的限制时,它非常有效,因为 Electron 将序列化通过 IPC 调用传递的所有数据。

我们前进的方式是使用 window.opener 功能。我们使用电子生成一个 main BrowserWindow,然后通过 window.open() 打开所需数量的 side 浏览器窗口。 Electron 可以在这些窗口生成时定位它们。 接下来,每个 side 窗口将其 HTML DOM 注册为 main 窗口的 JS 窗口实例。这样,main 窗口就引用了 side 窗口的 DOM 和 JS 窗口实例。 从这里开始,main 窗口可以完全控制所有可用的窗口,并且可以在所有窗口上呈现新的 HTML、传递 JS 对象、调用 JS 函数……。我们个人使用 React Portals 来处理不同窗口上的渲染。

目前我不能分享一个完整的例子,但如果我有时间我会创建一个 github 存储库。

一些已经可以帮助您前进的事情:

  • BrowserWindows 应具有相同的 affinity(参见 BrowserWindow docs
  • 启用您的 nativeWindowOpen 项网络首选项

仅供参考:您也可以直接在浏览器中使用此技术,但它们仍然不允许您在窗口中移动