3.electron中的菜单和系统托盘

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第7天,点击查看活动详情

Menu和Tray

相信大家在日常生活中也用过许多的桌面应用,比如说微信、QQ、网易云音乐等,这些应用都有一些共同点,比如说在页面上都有菜单,系统托盘上都有图标,右键托盘上的图标还有一个小菜单等等,今天就菜单和系统托盘,来看看怎样实现。

实现menu

在之前的文章中,大家构建了简单hello world的例子,本章在之前的基础上进行添加menu。

在目录下新建一个menu.js,内容如下:

const { Menu, BrowserWindow } = require('electron')
// 构建菜单结构
const template = [
  {
    label: 'parent-1',
    // submenu 代表子菜单
    submenu: [
      { 
          label: '创建新窗口' ,
          accelerator: 'ctrl+n', // 菜单的快捷方式
          click: () => {
            // 创建一个新的窗口
            let sonWin = new BrowserWindow({
              width: 200,
              height: 200,
            })
            sonWin.loadFile('./index2.html')
            // 为关闭的时候进行清空
            sonWin.on('close', () => {
              sonWin = null
            })
          }
      },
      { label: 'child-2' },
      { label: 'child-3' }
    ],
  },
  {
    label: 'parent-2',
    submenu: [
      { label: 'child-1' },
      { label: 'child-2' }
    ],
  },
]

// 在模板中创建菜单
const myMenu = Menu.buildFromTemplate(template)
// 为应用程序设置菜单
Menu.setApplicationMenu(myMenu)
复制代码

index.js中引入:

// 引入menu
require('./menu')
复制代码

在上边的例子中,通过electron内置的Menu添加了一些菜单,同时可以绑定快捷按键,以及对菜单的点击事件进行绑定,效果如下:

20220410_105558.gif 但是在现在的桌面应用中,很多都是将自带的菜单隐藏,然后自定义去开发菜单,那该如何隐藏呢!

方法有三如下:

方法1const electron = require('electron')
const Menu = electron.Menu
function createWindow (){
    Menu.setApplicationMenu(null)
}

方法2new BrowserWindow({autoHideMenuBar: true})

方法3new BrowserWindow({frame: false})
复制代码

image.png

细心的小伙伴可能会发现,窗口无法拖拽了,可以通过添加css方式实现拖拽:

body{ -webkit-app-region: drag;} // 可拖拽
body{ -webkit-app-region: no-drag;} // 禁止拖拽
复制代码

更多使用方法请参考官方文档哦 www.electronjs.org/zh/docs/lat…

添加Tray

image.png 大家都见过系统托盘,但是在electron中是怎么实现的呢,首先我们要先准备一个图标,然后在目录下新建一个tray.js,直接上代码:

// tray.js

const { app, Menu, Tray, nativeImage } = require('electron');
const path = require("path");

class HTray {
  constructor() {
    this.tray = null;
    this.normalImage = nativeImage.createFromPath(path.join(__dirname, "./build/icons/icon.ico")); // 托盘图标
  }

  createMenu() {
    const trayMenuTemplate = [
      {
        label: "显示/隐藏",
        click: function() {
          return app.win.isVisible() ? app.win.hide() : app.win.show();
        }
      },
      {
        label: "退出",
        click: function() {
          app.quit();
        }
      }
    ];
    const contextMenu = Menu.buildFromTemplate(trayMenuTemplate);
    this.tray.setToolTip("前端大狗");
    this.tray.setContextMenu(contextMenu);
  }

  show() {
    this.tray = new Tray(this.normalImage);
    this.createMenu();
    this.tray.on("click", () => {
      this.stopFlash();
      this.openWindow();
    });
  }

  openWindow() {
    app.win.isVisible() ? app.win.hide() : app.win.show();
    app.win.setSkipTaskbar(false);
  }
}

module.exports.HTray = HTray;
复制代码

为了方便使用,在这里将托盘的方法放到了class中,添加了右键菜单以及菜单的点击方法,效果等下演示哦!

用过电脑版微信的小伙伴应该都知道,点击托盘图标,微信会显示,在点击就会隐藏,来新消息图标会闪烁,咱们也来实现一下:

//tray.js

const { app, Menu, Tray, nativeImage } = require('electron');
const path = require("path");

class HTray {
  constructor() {
    this.tray = null;
    this.timer = null;
    this.normalImage = nativeImage.createFromPath(path.join(__dirname, "./build/icons/icon.ico")); // 托盘图标
    this.maskImage = nativeImage.createFromPath(path.join(__dirname, "./build/icons/empty.png")); // 空白图标,供闪烁使用
  }

  createMenu() {
    const trayMenuTemplate = [
      {
        label: "显示/隐藏",
        click: function() {
          return app.win.isVisible() ? app.win.hide() : app.win.show();
        }
      },
      {
        label: "退出",
        click: function() {
          app.quit();
        }
      }
    ];
    const contextMenu = Menu.buildFromTemplate(trayMenuTemplate);
    this.tray.setToolTip("前端大狗");
    this.tray.setContextMenu(contextMenu);
  }

  show() {
    this.tray = new Tray(this.normalImage);
    this.createMenu();
    this.tray.on("click", () => {
      this.stopFlash();
      this.openWindow();
    });
  }

  openWindow() {
    app.win.isVisible() ? app.win.hide() : app.win.show();
    app.win.setSkipTaskbar(false);
  }

  // 图标闪烁
  startFlash() {
    // 托盘闪烁
    let count = 0;
    this.timer = setInterval(() => {
      try {
        count++;
        if (count % 2 === 0) {
          this.tray.setImage(this.normalImage);
        } else {
          this.tray.setImage(this.maskImage);
        }
        if (count === 100) {
          count = 0;
        }
      } catch (err) {
        console.log(err);
        this.stopFlash();
      }
    }, 700);
  }

  // 停止闪烁
  stopFlash() {
    if (this.timer) {
      clearInterval(this.timer);
      this.timer = null;
    }
    this.tray.setImage(this.normalImage);
  }
}

module.exports.HTray = HTray;
复制代码

触发闪烁的操作是在渲染进程触发的,所以需要在index.html中添加以下代码;

<body>
  <div>闪烁测试</div>

  <button onclick="start()">开始闪烁</button>
  <button onclick="stop()">停止闪烁</button>

  <script>
    // ----------此处可忽略ipcRenderer, 后续章节会着重讲这里
    const { ipcRenderer } = require('electron');
    // 点击闪烁
    function start() {
      ipcRenderer.send("startFlash");
    }

    // 停止闪烁
    function stop() {
      ipcRenderer.send("stopFlash");
    }
  </script>
</body>
复制代码

当渲染进程发出信号时,需要在主进程进行接收:

// index.js

// 引入
const HTray = require('./tray').HTray

// 创建系统托盘
app.tray = new HTray();
// 显示系统托盘
app.tray.show();

// 托盘闪烁
ipcMain.on('startFlash', (event, arg) => {
    app.tray.startFlash();
})

// 停止闪烁
ipcMain.on('stopFlash', (event, arg) => {
    app.tray.stopFlash();
})

// 监听关闭事件
app.win.on('close', (event) => {
    // 1.隐藏窗口
    app.win.hide(); 
    // 2.隐藏任务栏
    app.win.setSkipTaskbar(true);
    // 3.阻止默认行为(因为并不是要关闭)
    event.preventDefault();
})
复制代码

原理就是通过切换图片来实现闪烁效果!!!!是不是很简单!!!! 到此为止,托盘的基本功能就结束啦,看下效果

20220410_113743.gif

更多功能请参考官方文档哦!www.electronjs.org/docs/latest…

感谢

谢谢你读完本篇文章,希望对你能有所帮助,如有问题欢迎各位指正。

我是Nicnic,如果觉得写得可以的话,请点个赞吧❤。

写作不易,「点赞」+「在看」+「转发」 谢谢支持❤

往期好文

《Javascript高频手写题1.0》

《Vue中生成图片验证码的小组件》

《前端JS高频面试题---1.发布-订阅模式》

《前端JS高频面试题---2.单例模式》

《前端JS高频面试题---3.代理模式》

《前端JS高频面试题---4.策略模式》

《前端CSS高频面试题---1.CSS选择器、优先级、以及继承属性》

《前端CSS高频面试题---2.em/px/rem/vh/vw的区别》

《前端CSS高频面试题---3.如何实现两栏布局,右侧自适应?三栏布局中间自适应呢?》

猜你喜欢

转载自juejin.im/post/7084816310739140615