Electron 自定义菜单、主进程与渲染进程通信
- 一、定义顶部菜单
- 二、Electron 自定义右键菜单
- 1、使用 @electron/remote 模块实现
- 三、 Electron 主进程和渲染进程通信
- 场景1:渲染进程给主进程发送异步消息
- 场景2:渲染进程给主进程发送异步消息,主进程接收到异步消息以后通知渲染进程
- 场景3:渲染进程给主进程发送同步消息
- 场景4: 主进程通知渲染进程执行操作
一、定义顶部菜单
单独写在一个 js 文件中,然后再在主进程中引入
// ipMain/menu.js
const { Menu, shell} = require('electron')let menuTemplate = [{labe: "文件",submenu: [{label: "新建文件",click: ()=>{console.log("Ctrl+N")}}]},{label: "编辑",submenu: [{label: "复制",role: "copy",click: ()=>{}}]},{role: 'help',submenu: [{label: 'Learn More',click: async () => {await shell.openExternal('https://electronjs.org')}}]}
]
let menuBuilder = Menu.buildFromTemplate(menuTemplate)
Menu.setApplicationMenu(menuBuilder)
// main.js
const {app, BrowserWindow} = require('electron')
const path = require('path')// 1、引入初始化remote 模块
const remote = require("@electron/remote/main")
remote.initialize()const createWindow = ()=>{const mainWindow = new BrowserWindow({width:800,height:600,webPreferences: {nodeIntegration: true,contextIsolation: false}})// __dirname 表示获取我们当前目录, path.join 会将两个参数合并成 d://electrondemo/index.htmlmainWindow.loadFile(path.join(__dirname, 'index.html'))// 打开调试模式// mainWindow.webContents.openDevTools()// 2、启用remote 模块remote.enable(mainWindow.webContents)require('./ipcMain/menu')
}// 监听 electron ready 事件创建窗口
app.on('ready', createWindow);
// 监听窗口关闭的事件,关闭的时候退出应用, macOs 需要排除
app.on('window-all-closed', ()=>{if(process.platform !=='darwin') {app.quit();}
})// Macos 中点击 dock 中的应用图标的时候重新创建窗口
app.on('activate', ()=>{if(BrowserWindow.getAllWindows().length === 0) {createWindow()}
})
二、Electron 自定义右键菜单
实现右键菜单有两种方法:
1、使用 @electron/remote 模块实现
2、使用主进程和渲染进程通信实现
1、使用 @electron/remote 模块实现
在 index.html 中引入下面文件
const remote= require('@electron/remote')
const Menu = remote.Menulet menuContextTemplate = [{label: "复制",role: "copy",click:()=>{console.log("copy")}},{label:'黏贴',role: "paste"}
]
let menuBuilder2 = Menu.buildFromTemplate(menuContextTemplate)
Menu.setApplicationMenu(menuBuilder2)window.onload = ()=>{window.addEventListener("contextmenu", (e)=>{console.log("鼠标点击了右键")e.preventDefault()menuBuilder2.popup({window: remote.getCurrentWindow() })},false)
}
三、 Electron 主进程和渲染进程通信
有时候我们想在渲染进程中通过一个事件去执行主进程里面的方法。或者在渲染进程中通知主进程处理事件,主进程处理完成后广播一个事件让渲染进程去处理一些事情。这个时候就用到了主进程和渲染进程之间的相互通信。
Electron 主进程和渲染进程的通信主要用到两个模块: ipcMain 和 ipcRenderer
ipcMain: 当在主进程中使用时,它处理从渲染器进程(网页)发送出来的异步和同步信息,当然也有可能从主进程向渲染进程发送消息。
ipcRenderer: 使用它提供的一些方法从渲染进程(web 页面)发送同步或者异步的消息到主进程。也可以接收主进程回复的消息。
场景1:渲染进程给主进程发送异步消息
// 主进程
const {ipcMain} = require("electron")
ipcMain.on("msg", (event, data)=>{// 接收事件对象以及 传递过来的参数console.log(event, data)
})// 渲染进程
const {ipcRenderer} = require("electron")window.onload = ()=>{let sendMsgDom = document.getElementById("sendMsg")sendMsgDom.onclick = ()=>{// 给主进程发送消息, 执行主进程中的方法ipcRenderer.send("msg", {name: "小星星"})}
}
实现效果:
场景2:渲染进程给主进程发送异步消息,主进程接收到异步消息以后通知渲染进程
// 主进程
const {ipcMain} = require("electron")
ipcMain.on("sendMsg", (event, data)=>{// 接收事件对象以及 传递过来的参数console.log(event, data)
})
ipcMain.on("sendMsgReply", (event, data)=>{// 接收事件对象以及 传递过来的参数console.log(event, data)//给渲染进程回复消息event.sender.send('replyRenderer',"accept msg")
})
// 渲染进程
const {ipcRenderer} = require("electron")window.onload = ()=>{let sendMsgDom = document.getElementById("sendMsg")sendMsgDom.onclick = ()=>{// 给主进程发送消息, 执行主进程中的方法ipcRenderer.send("sendMsg", {name: "小星星"})}let sendMsgReplyDom = document.getElementById("sendMsgReply")sendMsgReplyDom.onclick = ()=>{// 给主进程发送消息, 执行主进程中的方法ipcRenderer.send("sendMsgReply", 'this is ipcRenderer msg,need reply me')}// 监听主进程的广播ipcRenderer.on("replyRenderer", (e, data)=>{console.log(data)})
}
场景3:渲染进程给主进程发送同步消息
// 主进程
const {ipcMain} = require("electron")
ipcMain.on("sendSyncMsg", (event, data)=>{// 接收同步消息console.log(event, data)event.returnValue = "hello, I am ipcMain"
})
// 渲染进程
const {ipcRenderer} = require("electron")
window.onload = ()=>{let sendMsgSyncDom = document.getElementById("sendMsgSync")sendMsgSyncDom.onclick = ()=>{// 同步发送消息let replyInfo = ipcRenderer.sendSync("sendSyncMsg", "I am ipcRenderer")console.log("reply:", replyInfo)}
}
场景4: 主进程通知渲染进程执行操作
// 主进程BrowserWindow.getFocusedWindow().webContents.send("reply", "BrowserWindow reply")
// 渲染进程
const {ipcRenderer} = require("electron")
// 监听主进程主动发送过来的消息ipcRenderer.on("reply", (event, data)=>{console.log(event, data)})
渲染进程中获取当前窗口的方法 :
remote.getCurrentWindow()
主进程中获取当前窗口的方法:
BrowserWindow.getFocusedWindow()