目录
- 项目初始化可以看官网非常详细
- 根路径创建.vscode文件夹
- 主进程和渲染进程之前的通信
- `ipcRenderer.send`和`ipcMain.on`的使用
- `ipcRenderer.invoke`和`ipcMain.handle`的使用
- 切换主题模式
- 文件拖放保存
- 消息通知
- 进度展示
- 图标闪烁
- 自定义菜单
- 自定义右键菜单
项目初始化可以看官网非常详细
快速入门
主要需要看下窗口的配置
const win = new BrowserWindow({width: 800,height: 600,center: true,// frame: false, //创建无边框窗口// titleBarStyle: "hidden", //隐藏默认的标题栏// 隐藏菜单// autoHideMenuBar: true,webPreferences: {preload: path.join(__dirname, "preload.js"),webviewTag: true, //允许使用<webview>标签// offscreen: true, //离屏渲染},});
根路径创建.vscode文件夹
创建launch.json
文件,用来调试
{"version": "0.2.0","compounds": [{"name": "Main + renderer","configurations": ["Main", "Renderer"],"stopAll": true}],"configurations": [{"name": "Renderer","port": 9222,"request": "attach","type": "chrome","webRoot": "${workspaceFolder}"},{"name": "Main","type": "node","request": "launch","cwd": "${workspaceFolder}","runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron","windows": {"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron.cmd"},"args": [".", "--remote-debugging-port=9222"],"outputCapture": "std","console": "integratedTerminal"}]
}
主进程和渲染进程之前的通信
ipcRenderer.send
和ipcMain.on
的使用
preload.js
中引入contextBridge, ipcRenderer
进行消息注册
const { contextBridge, ipcRenderer } = require("electron");contextBridge.exposeInMainWorld("myAPI", {setTitle: (title) => {ipcRenderer.send("set-title", title);},
});
main.js
中进行消息处理
app.on("ready", () => {// 设置标题ipcMain.on("set-title", handleSetTitle);createWindow();
});/*** @description 设置title*/
function handleSetTitle(event, title) {const webContents = event.sender;const win = BrowserWindow.fromWebContents(webContents);win.setTitle(title);
}
renderer.js
中触发事件,修改title
<h1>ipcRenderer.send-ipcMain.on的使用</h1><input id="title"></input>
<button id="set-title">修改title</button>
/*** @description 修改窗口title*/
const titleEl = document.getElementById("title");
const handleTitleBtn = document.getElementById("set-title");
handleTitleBtn.addEventListener("click", () => {window.myAPI.setTitle(titleEl.value);
});
ipcRenderer.invoke
和ipcMain.handle
的使用
和send-on的区别主要在于可以双向通信
preload.js
const { contextBridge, ipcRenderer } = require("electron");contextBridge.exposeInMainWorld("myAPI", {openFile: () => ipcRenderer.invoke("dialog:openFile"),
});
main.js
app.on("ready", () => {// 获取文件ipcMain.handle("dialog:openFile", handleOpenFile);createWindow();
});/*** @description 打开文件选择弹窗*/
async function handleOpenFile() {const { canceled, filePaths } = await dialog.showOpenDialog({});if (!canceled) {return filePaths[0];//返回值给invoke}
}
renderer.js
<button type="button" id="file-btn">Open a File</button>File path: <strong id="file-path"></strong>
/*** @description 打开文件*/
const handleFileBtn = document.getElementById("file-btn");
const filePath = document.getElementById("file-path");
handleFileBtn.addEventListener("click", async () => {const path = await window.myAPI.openFile();filePath.innerHTML = path;
});
切换主题模式
const {dialog,nativeTheme,globalShortcut,nativeImage,
} = require("electron");app.on("ready", () => {// 设置主题ipcMain.handle("trigger-mode", triggerMode);createWindow();
});/*** @description 设置主题*/
function triggerMode() {if (nativeTheme.shouldUseDarkColors) {nativeTheme.themeSource = "light";} else {nativeTheme.themeSource = "dark";}return nativeTheme.shouldUseDarkColors;
}
文件拖放保存
- 注册事件
contextBridge.exposeInMainWorld("myAPI", {startDrag: (fileName) => ipcRenderer.send("ondragstart", fileName),
});
- 处理事件
app.on("ready", () => {// 文件的拖放保存ipcMain.on("ondragstart", fileDrag);createWindow();
});/*** @description 原生文件拖放*/
function fileDrag(event, filePath) {// 文件拖放const iconName = path.join(__dirname, "doc.png"); //iconevent.sender.startDrag({file: path.join(__dirname, filePath),icon: iconName,});
}
- 给元素添加拖拽事件
/*** @description 原生文件的拖拽*/
document.getElementById("drag").ondragstart = (event) => {event.preventDefault();window.myAPI.startDrag("test.txt");
};
- 根路径准备一个
test.txt
文件
消息通知
//main.js
app.on("ready", () => {createWindow();ipcMain.on("open-message", openMessage);
});/*** @description 打开消息*/
function openMessage(event, message) {const notice = new Notification({title: "消息",body: message,});notice.show();notice.on("click", () => {console.log("点击了通知");});
}
进度展示
//main.js
app.on("ready", () => {// 设置进度条ipcMain.handle("progress", setProgress);createWindow();
});/*** @description 设置进度条*/
function setProgress(event, num) {const webContents = event.sender;const win = BrowserWindow.fromWebContents(webContents);if (num >= 1) {win.setProgressBar(-1); //-1完成return true;} else {win.setProgressBar(num);//num:0-1return false;}
}
图标闪烁
//main.js
app.on("ready", () => {// 闪烁ipcMain.on("flash", setFlash);createWindow();
});/*** @description 设置闪烁*/
function setFlash(event) {const webContents = event.sender;const win = BrowserWindow.fromWebContents(webContents);win.flashFrame(true);
}
自定义菜单
/*** @description 添加菜单*/
function addMenu() {const menu = new Menu();const submenu = new Menu();menu.append(new MenuItem({ label: "测试", submenu }));Menu.setApplicationMenu(menu);submenu.append(new MenuItem({ label: "测试1" }));
}
自定义右键菜单
- 监听右键菜单
//renderer.js/*** @description 监听右键菜单*/window.addEventListener("contextmenu", async (e) => {e.preventDefault();const menu = [{label: "Run Code",click: true,},{label: "转到定义",click: true,},{type: "separator",},{label: "复制",click: true,},];const clickOne = await window.myAPI.addContextMenu(menu);console.log(clickOne);});
- 添加菜单
//main.js
/*** @description 添加右键菜单*/
function addContextMenu(event, contextMenu) {return new Promise((resolve) => {const menuReal = contextMenu.map((item) => {if (item.click) {return {...item,click: () => {resolve(item.label);},};} else {return item;}});const menu = Menu.buildFromTemplate(menuReal);menu.popup({window: BrowserWindow.fromWebContents(event.sender),});});
}