electron系统托盘及消息闪动提示

6,479 阅读2分钟

微信启动时,系统托盘中会自动添加一个微信启动程序图标

img
使用electron如何实现这种效果昵?废话不多说,直接开干

概述

1.将桌面应用放入系统托盘

electron/Tray官方文档

// electron index.js中
....
import { app, BrowserWindow, ipcMain, Menu, Tray, nativeImage } from 'electron'
....
let tray = null
app.on('ready', () => {
  tray = new Tray('/path/to/my/icon')  // 坑①
  // 右键菜单
  const contextMenu = Menu.buildFromTemplate([
    {
      label: '微信',
      role: 'redo',
      click: () => {
        if (win) {
          win.show()
        }
      }
    },
    { label: '退出微信', role: 'quit' }
  ])
  tray.setToolTip('微信')
  tray.setContextMenu(contextMenu)
  tray.on('click', (event,bounds,position) => {  // 监听单击做的时
    console.log(event,bounds,position)
    if (win.isVisible()) {
      win.hide()
    } else {
      win.show()
    }
  })
})

2.右键菜单

参考electron/Menu官方文档

// 在菜单角色中有许多选项
role 属性可以具有以下值:
    undo: 撤消
    redo: 重做
    cut: 剪切
    copy:复制
    paste: 粘贴
    pasteAndMatchStyle:粘贴和匹配样式
    selectAll: 全选
    delete: 删除
    minimize - 最小化当前窗口。
    close - 关闭当前窗口.
    quit - 退出当前应用.
    reload - 重新加载当前窗口。
    forcereload - 忽略缓存,重新加载当前窗口。
    toggledevtools - 在当前窗口中隐藏/显示开发者工具。
    toggleFullScreen - Toggle full screen mode on the current window.
    resetzoom - 将主页的缩放级别重置为初始大小.
    zoomin - 主页面放大 10%.
    zoomout -主页面缩小 10%.
    fileMenu - Whole default "File" menu (Close / Quit)
    editMenu-默认的 "编辑" 菜单 (包括撤消、复制等)
    viewMenu - Whole default "View" menu (Reload, Toggle Developer Tools, etc.)
    windowMenu - Whole default "Window" menu (Minimize, Zoom, etc.).

3.消息闪动

当微信收到消息的时候,桌面应用会闪动,并且伴随有声音提示

推送一条未读新消息闪烁,其原理不同时刻图标切换。

// 桌面应用消息闪动
app.on('ready', () => {
  let timer = null
  let count = 0
  ...
  // 这里是将桌面应用放入系统托盘的代码
  ...
  // 渲染线程通知,有新的消息
  ipcMain.on('haveMessage', (event,arg) => {
    timer = setInterval(() => {
      count += 1
      if (count % 2 === 0) {
        tray.setImage(icon)
      } else {
        tray.setImage(nativeImage.createEmpty()) // 创建一个空的nativeImage实例
      }
      tray.setToolTip('您有一条新消息')
    }, 500)
  })
  tray.on('click', () => {
    if (win.isVisible()) {
      win.hide()
    } else {
      win.show()
      tray.setImage(icon)
      tray.setToolTip('私塾国际学府')
      clearInterval(timer)
      timer = null
      count = 0
    }
  })
})

声音提示

若对方发送一条未读消息,提示用户滴滴滴声音🔊......至于音频(使用HTML5 Audio即可)什么时候停止,取决你对用户的界定.

<script>
	exports default {
    	methods: {
            haveMessage() {
                this.$electron.ipcRenderer.send('haveMessage') 
                // 这里可以放一个较短的声音文件
                const audio = new Audio('/path/to/my/audio')
                audio.play()               
            },
        }
    }
</script>

4.坑!!!!!

  • 坑点一

官方文档上面写的是tray = new Tray('/path/to/my/icon'), 而当我们高高兴兴的将路径放入这个 new Tray() 中, yarn dev,让代码跑一会..... 发现ε=(´ο`*)))唉,我系统图标呢?我写了的啊?怎么没了?

扒拉官方文档,看见一个好东西

new Tray(image)

image (NativeImage | String)

​ 创建与image关联的新任务栏图标。

好的,那就试试nativeImagetray = new Tray(nativeImage('/path/to/my/icon'))yarn dev,让代码跑一会..... 还好,还好,系统图标出现了

  • 坑点二

程序写完了,试试打包后的结果,yarn build ,让代码跑好一会.......,安装,运行,发现ε=(´ο`*)))唉,我系统图标呢?我写了的啊?怎么没了?dev环境是正常运行的啊怎么没了?

源码分析,是不是头标不该放在render这个文件夹中?是不是头标的图片格式不正确?一顿混乱操作,结果发现,怎么还是没有?

asar分析,是不是头标没有打包进去?

$ yarn global add asar
$ asar e app.asar test

又是一顿混乱的操作,发现头标打包进去了!!

路径分析,是不是路径写的不对?但是在dev环境下是可以运行的!!查看路径:path居然不对!!!

修改代码

const iconUrl = process.env.NODE_ENV === 'development' ? path.join(__dirname, '../../static/favicon.ico') : path.join(__dirname, 'static/favicon.ico')

const icon = nativeImage.createFromPath(iconUrl)

yarn build ,让代码跑好一会.......,安装,运行,终于看见头标了!!!!