一起养成写作习惯!这是我参与「掘金日新计划 · 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添加了一些菜单,同时可以绑定快捷按键,以及对菜单的点击事件进行绑定,效果如下:
但是在现在的桌面应用中,很多都是将自带的菜单隐藏,然后自定义去开发菜单,那该如何隐藏呢!
方法有三如下:
方法1:
const electron = require('electron')
const Menu = electron.Menu
function createWindow (){
Menu.setApplicationMenu(null)
}
方法2:
new BrowserWindow({autoHideMenuBar: true})
方法3:
new BrowserWindow({frame: false})
复制代码
细心的小伙伴可能会发现,窗口无法拖拽了,可以通过添加css方式实现拖拽:
body{ -webkit-app-region: drag;} // 可拖拽
body{ -webkit-app-region: no-drag;} // 禁止拖拽
复制代码
更多使用方法请参考官方文档哦 www.electronjs.org/zh/docs/lat…
添加Tray
大家都见过系统托盘,但是在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();
})
复制代码
原理就是通过切换图片来实现闪烁效果!!!!是不是很简单!!!! 到此为止,托盘的基本功能就结束啦,看下效果
更多功能请参考官方文档哦!www.electronjs.org/docs/latest…
感谢
谢谢你读完本篇文章,希望对你能有所帮助,如有问题欢迎各位指正。
我是Nicnic,如果觉得写得可以的话,请点个赞吧❤。
写作不易,「点赞」+「在看」+「转发」 谢谢支持❤
往期好文
《前端CSS高频面试题---1.CSS选择器、优先级、以及继承属性》