• Electron的学习


    项目初始化可以看官网非常详细

    快速入门
    主要需要看下窗口的配置

      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, //允许使用标签
          // offscreen: true, //离屏渲染
        },
      });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    根路径创建.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"
        }
      ]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    主进程和渲染进程之前的通信

    ipcRenderer.sendipcMain.on的使用
    1. preload.js中引入contextBridge, ipcRenderer进行消息注册
    const { contextBridge, ipcRenderer } = require("electron");
    
    contextBridge.exposeInMainWorld("myAPI", {
      setTitle: (title) => {
        ipcRenderer.send("set-title", title);
      },
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    1. 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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    1. renderer.js中触发事件,修改title
    <h1>ipcRenderer.send-ipcMain.on的使用h1>
    	<input id="title">input>
    <button id="set-title">修改titlebutton>
    
    • 1
    • 2
    • 3
    /**
     * @description 修改窗口title
     */
    const titleEl = document.getElementById("title");
    const handleTitleBtn = document.getElementById("set-title");
    handleTitleBtn.addEventListener("click", () => {
      window.myAPI.setTitle(titleEl.value);
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    ipcRenderer.invokeipcMain.handle的使用

    和send-on的区别主要在于可以双向通信

    1. preload.js
    const { contextBridge, ipcRenderer } = require("electron");
    
    contextBridge.exposeInMainWorld("myAPI", {
      openFile: () => ipcRenderer.invoke("dialog:openFile"),
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    1. 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
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    1. renderer.js
        <button type="button" id="file-btn">Open a Filebutton>
        File path: <strong id="file-path">strong>
    
    • 1
    • 2
    /**
     * @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;
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

    切换主题模式

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    在这里插入图片描述

    文件拖放保存

    1. 注册事件
    contextBridge.exposeInMainWorld("myAPI", {
      startDrag: (fileName) => ipcRenderer.send("ondragstart", fileName),
    });
    
    • 1
    • 2
    • 3
    1. 处理事件
    app.on("ready", () => {
      // 文件的拖放保存
      ipcMain.on("ondragstart", fileDrag);
      createWindow();
    });
    
    /**
     * @description 原生文件拖放
     */
    function fileDrag(event, filePath) {
      // 文件拖放
      const iconName = path.join(__dirname, "doc.png"); //icon
      event.sender.startDrag({
        file: path.join(__dirname, filePath),
        icon: iconName,
      });
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    1. 给元素添加拖拽事件
    /**
     * @description 原生文件的拖拽
     */
    document.getElementById("drag").ondragstart = (event) => {
      event.preventDefault();
      window.myAPI.startDrag("test.txt");
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    1. 根路径准备一个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("点击了通知");
      });
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    在这里插入图片描述

    进度展示

    //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-1
        return false;
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    在这里插入图片描述
    在这里插入图片描述

    图标闪烁

    //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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在这里插入图片描述

    自定义菜单

    /**
     * @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" }));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述

    自定义右键菜单

    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);
      });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    1. 添加菜单
    //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),
        });
      });
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
  • 相关阅读:
    区别:b、B、KB、M、MB、GB、TB、PB、EB、ZB、YB、BB以及它们之间的关系
    图像边缘检测--(Sobel、Laplacian、Canny)
    SMTP 协议研究
    #每日一题合集#牛客JZ44-JZ53
    Android之 SVG绘制
    Kubernetes学习(二)你不得不了解的K8s核心组件
    四元数与其在Unity中的简单应用
    经典BN很NB,精读论文《Batch Normalization》
    python实现自动换桌面壁纸恶搞程序【带源码】--------- 2.程序调试和打包
    每日一题AC
  • 原文地址:https://blog.csdn.net/qq_44775782/article/details/137236460