• electron自定义快捷窗口按钮,大小窗口切换


    关注公众号: 微信搜索 前端工具人 ; 收货更多的干货

    原文链接: 自己掘金文章: https://juejin.cn/post/7067815153374330888/

    一、需求

    主要是一下几个常见的需求:

    • 自定义顶部菜单栏, 可拖拽;
    • 自定义最小化、最大化、退出按钮、刷新按钮(类似浏览器的重新加载、用于开发阶段调试);
    • 小窗口 - 中窗口 - 全屏窗口, 相互切换;

    二、electron 解读

    electron 区分了两种进程:主进程和渲染进程

    2.1 主进程:

    • 创建进程、窗口...
    • 控制应用生命周期(启动、退出APP、事件监听..)
    • 调用系统底层功能 (Electron API)、调用原生APINode.js 与本地交互...)

    2.2 渲染进程

    • 主要是内置 Chromium 浏览, 来实现页面的渲染;
    • 可以理解成 electron 渲染进程 为 Chromium 的窗口; 所以和日常开发区别不大

    三、需求实现

    项目入口文件 render.js, 主进程事件文件 ipc.event.js

    render.js

    'use strict'
    
    import { app, protocol, BrowserWindow, Menu } from 'electron'
    import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'
    // import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'
    import initIpcEvent from './services/ipc.event'
    const path = require('path');
    
    const isDevelopment = process.env.NODE_ENV !== 'production'
    
    // Scheme must be registered before the app is ready
    protocol.registerSchemesAsPrivileged([
      { scheme: 'app', privileges: { secure: true, standard: true } }
    ])
    
    async function createWindow () {
      // Create the browser window.
      const win = new BrowserWindow({
         400,
        height: 500,
        center: true,
        frame: false,
        useContentSize: true,
        // resizable: false,
        webPreferences: {
          webSecurity: false,
          enableRemoteModule: true,
          // Use pluginOptions.nodeIntegration, leave this alone
          // See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
          nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
          contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION
        },
        icon: path.join(__dirname, '../public/favicon32.ico')
      })
    
      if (process.env.WEBPACK_DEV_SERVER_URL) {
        // Load the url of the dev server if in development mode
        await win.loadURL(process.env.WEBPACK_DEV_SERVER_URL)
        // win.webContents.openDevTools()
        if (!process.env.IS_TEST) win.webContents.openDevTools()
      } else {
        createProtocol('app')
        // Load the index.html when not in development
        win.loadURL('app://./index.html')
      }
      win.setMenu(null)
      global.mainWindow = win
      // 初始化进程之间事件监听
      initIpcEvent()
      // 隐藏菜单
      createMenu()
    }
    
    // Quit when all windows are closed.
    app.on('window-all-closed', () => {
      // On macOS it is common for applications and their menu bar
      // to stay active until the user quits explicitly with Cmd + Q
      if (process.platform !== 'darwin') {
        app.quit()
      }
    })
    
    app.on('activate', () => {
      // On macOS it's common to re-create a window in the app when the
      // dock icon is clicked and there are no other windows open.
      if (BrowserWindow.getAllWindows().length === 0) createWindow()
    })
    
    // This method will be called when Electron has finished
    // initialization and is ready to create browser windows.
    // Some APIs can only be used after this event occurs.
    app.on('ready', async () => {
      if (isDevelopment && !process.env.IS_TEST) {
        // Install Vue Devtools
        try {
          // await installExtension(VUEJS_DEVTOOLS)
        } catch (e) {
          console.error('Vue Devtools failed to install:', e.toString())
        }
      }
      createWindow()
    })
    
    // Exit cleanly on request from parent process in development mode.
    if (isDevelopment) {
      if (process.platform === 'win32') {
        process.on('message', (data) => {
          if (data === 'graceful-exit') {
            app.quit()
          }
        })
      } else {
        process.on('SIGTERM', () => {
          app.quit()
        })
      }
    }
    
    // 设置菜单栏
    function createMenu() {
      // darwin表示macOS,针对macOS的设置
      if (process.platform === 'darwin') {
        const template = [{
          label: 'Electron',
          submenu: [{
            role: 'about'
          }, {
            role: 'quit'
          }]
        }]
        const menu = Menu.buildFromTemplate(template)
        Menu.setApplicationMenu(menu)
      } else {
        // windows及linux系统
        Menu.setApplicationMenu(null)
      }
    }
    
    

    ipc.event.js

    import { ipcMain, app, BrowserWindow } from 'electron'
    
    export default function () {
      ipcMain.on('toggle-mini', (event, params) => {
        if (params.value) {
          global.mainWindow.hide()
        } else {
          global.mainWindow.show()
        }
      })
    
      ipcMain.on('window-min', () => {
        global.mainWindow.minimize()
        global.mainWindow.setResizable(true)
      })
    
      ipcMain.on('window-login', () => {
        global.mainWindow.setMinimumSize(400, 500)
        global.mainWindow.center()
        global.mainWindow.setResizable(false)
      })
    
      ipcMain.on('window-password', () => {
        global.mainWindow.setSize(1366, 768)
        global.mainWindow.center()
        global.mainWindow.setResizable(true)
      })
    
      ipcMain.on('window-max', () => {
        if (global.mainWindow.isMaximized()) {
          global.mainWindow.restore()
        } else {
          global.mainWindow.maximize()
        }
        // global.mainWindow.setMinimumSize(1600, 900)
        global.mainWindow.setMinimumSize(1200, 800)
        global.mainWindow.center()
      })
    
      ipcMain.on('window-hide', () => {
        global.mainWindow.hide()
      })
    
      ipcMain.on('window-show', () => {
        global.mainWindow.show()
      })
    
      ipcMain.on('window-refresh', () => {
        global.mainWindow.reload();
      })
    
      // 关闭当前窗口
      ipcMain.on('window-close', () => {
        console.log("window-close")
        global.mainWindow.close()
      })
    
      // 关闭所有窗口
      ipcMain.on('window-all-close', () => {
        console.log("window-all-close")
        const wins = BrowserWindow.getAllWindows()
        for (let i = 0; i < wins.length; i++) {
          wins[i].close()
        }
      })
    
      // 所有窗口都将立即被关闭,而不询问用户,而且 before-quit 和 will-quit 事件也不会被触发。
      ipcMain.on('app-exit', () => {
        app.exit()
      })
    
      ipcMain.on('quit-and-open', (event, data) => {
        global.downloadFile = data
        app.quit()
      })
    }
    
    

    3.1 自定义顶部导航栏

    首先要隐藏调自带的顶部导航栏

    // createMenu() 方法就是隐藏顶部导航栏
    / 拖拽,样式  -webkit-app-region: drag;
    

    3.2 自定义最小化、最大化、退出按钮、刷新按钮;

    <!-- 顶部导航栏 -->
    <template>
      ...
      <header class="common-header">
        <i class="el-icon-refresh-right" title="刷新" @click="onChangeWindow('refresh')"></i>
        <i class="el-icon-switch-button" title="退出登录" @click="onChangeWindow('logout')"></i>
        <i class="el-icon-minus" title="最小化" @click="onChangeWindow('min')"></i>
        <i v-show="isMax" class="el-icon-copy-document" title="还原" @click="onChangeWindow('scale')"></i>
        <i v-show="!isMax" class="max-window" title="最大化" @click="onChangeWindow('scale')">
          <span></span>
        </i>
        <i class="el-icon-close" title="关闭" @click="onChangeWindow('close')"></i>
      </header>
      ...
    </template>
    <script>
    import { ipcRenderer, remote } from 'electron'
    ...
    // 窗口切换
    onChangeWindow (type) {
      switch (type) {
        case 'min':
          ipcRenderer.send('window-min')
          break;
        case 'scale':
          ipcRenderer.send('window-max')
          const winInfo = remote.getCurrentWindow()
          this.isMax = winInfo.isMaximized()
          break;
        case 'close':
          ipcRenderer.send('window-min')
          break;
        case 'logout':
          ipcRenderer.send('window-min')
          setTimeout(() => {
            this.$router.push('/')
            ipcRenderer.send('window-login')
            ipcRenderer.send('window-show')
          }, 150)
          break;
        case 'refresh':
          ipcRenderer.send('window-refresh')
          break;
      }
    ...
    </script>
    

    3.3 小窗口 - 中窗口 - 全屏窗口, 相互切换;

    • 初始化登录界面是小窗口类似于微信登录一样 400 * 500
    • 登录后跳转到程序主界面, 全屏
    • 忘记密码界面(中窗口)1366 * 788

    自己开发时,在全屏状态下切换回小窗口切换不了,百度了蛮久,也没结果;

    后面发现改变全屏状态后就能切换...

    方法:先最小化窗口、在 setMinimumSize 改变尺寸, 在显示, 相当于加了个过渡一下,变换过程也没那么死板

    具体看3.2onChangeWindow 里的 logout 方法

    有不对之处欢迎指正, 代码有删减,没做测试;

    只是作为分享,让有需要的少走弯路,节省百度时间

  • 相关阅读:
    SA(后缀数组)专题总结
    LCT总结
    多项式全家桶
    fft.ntt,生成函数,各种数和各种反演
    P3939 数颜色
    P1879 [USACO06NOV]玉米田Corn Fields
    主席树模板
    P2633 Count on a tree
    P1972 [SDOI2009]HH的项链
    数论
  • 原文地址:https://www.cnblogs.com/ljx20180807/p/15927975.html
Copyright © 2020-2023  润新知