Je crée plusieurs fenêtres à partir du processus principal d'Electron et je dois faire passer des messages entre elles. Le seul moyen que j'ai trouvé pour envoyer des messages du moteur de rendu A au moteur de rendu B est de les faire rebondir sur le processus principal. Existe-t-il un moyen d'envoyer directement un message du moteur de renduA au moteur de renduB ?
Réponses
Trop de publicités?D'une manière ou d'une autre, le processus principal doit être impliqué, mais la communication entre les processus de rendu de deux fenêtres peut être réalisée d'une manière assez simple :
-
Dans le processus principal, définissez les références de la fenêtre comme des propriétés de l'objet global ;
-
Dans chaque processus de rendu, accédez à la référence de la fenêtre à laquelle vous voulez envoyer un message en utilisant remote.getGlobal (), puis utilisez la méthode send () ;
-
Utilisez ipcRenderer.on () de la manière habituelle pour recevoir le message dans chaque processus de rendu.
Voici un Exemple rapide d'une application Electron qui fait exactement cela :
main.js :
const { app, BrowserWindow } = require ('electron');
global.window1 = null;
global.window2 = null;
function onAppReady ()
{
window1 = new BrowserWindow ({ width: 600, height: 500 });
window1.loadURL (`file://${__dirname}/index1.html`);
window1.webContents.openDevTools ();
window1.on ('closed', () => { window1 = null; });
//
window2 = new BrowserWindow ({ width: 500, height: 600 });
window2.loadURL (`file://${__dirname}/index2.html`);
window2.webContents.openDevTools ();
window2.on ('closed', () => { window2 = null; });
}
app.on ('ready', onAppReady);
app.on ('window-all-closed', () => { app.quit (); });
index1.html :
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Window 1</title>
</head>
<body>
<h1>Window 1</h1>
<button type="button" class="send-message">Send Message to Window 2</button>
<script>
const { remote, ipcRenderer } = require ('electron');
//
let button = document.querySelector ('.send-message');
button.addEventListener ('click', () =>
{
let window2 = remote.getGlobal ('window2');
if (window2) window2.webContents.send ('message', "Message from Window 1");
});
//
ipcRenderer.on ('message', (event, message) => { console.log (message); });
</script>
</body>
</html>
index2.html :
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Window 2</title>
</head>
<body>
<h1>Window 2</h1>
<button type="button" class="send-message">Send Message to Window 1</button>
<script>
const { remote, ipcRenderer } = require ('electron');
//
let button = document.querySelector ('.send-message');
button.addEventListener ('click', () =>
{
let window1 = remote.getGlobal ('window1');
if (window1) window1.webContents.send ('message', "Message from Window 2");
});
//
ipcRenderer.on ('message', (event, message) => { console.log (message); });
</script>
</body>
</html>
Fondamentalement, dans l'électronique, les communications entre les processus ont trois formes :
- principal -> moteur de rendu :
webContents.fromId(id).send()
du côté de l'émetteur,ipcRenderer.on
du côté du récepteur - renderer -> main :
ipcRenderer.send()
du côté de l'émetteur,ipcMain.on
du côté du récepteur - moteur de rendu -> moteur de rendu :
ipcRenderer.sendTo()
du côté de l'émetteur,ipcRenderer.on
du côté du récepteur
Ainsi, dans un scénario de rendu à rendu, l'expéditeur doit connaître le webContents.id de la destination, puis l'appeler de/vers via ipcRenderer.sendTo()
J'ai créé un cadre d'ipc électronique, électron-ipcfy qui unifie les appels ipc dans les trois scénarios ci-dessus.
import { ipcfy } from "electron-ipcfy";
interface TestService {
greet(name: string);
}
const testService = ipcfy<TestService>('test');
if (process.type == 'browser') {
// Attach implementation
testService.__attachImpl(
new class implements TestService {
greet(name: string) {
console.log(`Hello, ${name}!`);
}
});
}
// Then you can call it in any process
testService.greet('world');
Cela dépend de la logique de votre système de communication.
Par exemple, si vous devez toujours envoyer des données du BrowserWindow2 vers le BrowserWindow4, vous pouvez déclarer l'attribut ipcMain dans la BrowserWindow4 et ipcRenderer dans la BrowserWindow2.
Dans le cas où vous devez envoyer des messages de toutes les BrowserWindows vers toutes les autres, je vous conseille d'utiliser le processus Main et d'envoyer des messages aux BrowserWindows (en utilisant les relatives ID )
Dans votre destinataire du message :
ipcMain.on('asynchronous-message', (event, arg) => {
//manage data
}
Et dans votre émetteur du message :
ipcRenderer.send('asynchronous-message', message)