Como personalizar uma barra de menu do sistema com a altura do elétron?

fundo

Recentemente, eu estava trabalhando em um cliente de PC de bate-papo em tempo real e encontrei uma tarefa dessas. Quando o cliente recebe mensagens de outros usuários, ele deve piscar o ícone da bandeja do sistema e exibir a barra de menu de mensagens não lidas quando o mouse se move para a bandeja do sistema ( Sim, é um prompt de mensagem semelhante ao QQ, como a imagem abaixo); aqui para adicionar, escolhemos electron como nosso framework de desenvolvimento, para nós, electron pode usar linguagem front-end (HTML + CSS + JS), e pode ser multiplataforma A estrutura é nossa melhor escolha.

Como personalizar uma barra de menu do sistema com a altura do elétron?

Ideias para resolução de problemas

1. O pensamento das pessoas normais é primeiro verificar se o elétron tem API integrada. Não sou exceção, então olhei em volta e encontrei um módulo de bandeja do sistema. O modelo aproximado da API se parece com este:

const { app, Menu, Tray } = require('electron')
let tray = null;
let openVoice = true;
app.whenReady().then(() => {
  tray = new Tray('/path/to/my/icon');
  const contextMenu = Menu.buildFromTemplate([
    {
        label: openVoice ? '关闭声音' : '开启声音',
        icon: openVoice ? "trayMenu/notVoice.png": "trayMenu/voice.png",
        click: (event: any) => {
            openVoice = !openVoice;
        },
    },
    {
        label: '退出',
        icon:  "trayMenu/exit.png",
        click: () => {
            app.exit(0);
        }
    }
  ]);
  tray.setToolTip('This is my application.')
  tray.setContextMenu(contextMenu)
})

O efeito real é provavelmente assim:
Como personalizar uma barra de menu do sistema com a altura do elétron?

De um modo geral, ele oferece suporte a itens mais gerais, como títulos, ícones, submenus e chamadas de retorno de clique. Parece que há uma grande lacuna em relação aos nossos ideais. Se eu não acredito no mal, gostaria de tentar se posso suportar renderização de HTML, então apenas adiciono contextMenu Mais um subitem:

{
    label: '<p style="backgroud: #red">测试</p>',
    icon:  "trayMenu/exit.png",
    click: () => {
        app.exit(0);
    }
}

O resultado também é mais comovente, é exatamente a saída que escrevi, parece que dessa forma não está funcionando;

2. Personalize você mesmo uma barra de menu do sistema

De acordo com nosso ponto de prática anterior, podemos basicamente ver que a bandeja do sistema é basicamente inútil para nós, exceto para criar um ícone de bandeja; portanto, pensei em usar uma janela do navegador (BrowserWindow) como a barra de menu, para que a barra de menu seja feita Parece que está totalmente em nossas mãos, mas primeiro devemos resolver os seguintes problemas:

1. Como monitorar o deslizamento do mouse para o ícone da bandeja

Primeiro criamos a janela da barra de menu correspondente, que está oculta por padrão

menuWin = new BrowserWindow({
    modal: true,
    autoHideMenuBar: true,
    disableAutoHideCursor: true, 
    frame: false,
    show: false,
});
menuWin.loadURL(config.frontUrl + '/#/newMessage'); // 加载对应的菜单栏页面

Procurei a API da bandeja e só encontrei um evento de movimento do mouse para lidar com esse problema, mas esse evento só é acionado quando desliza para a bandeja e não há evento correspondente para puxar a bandeja, então temos que fazer Mecanismo para determinar se o mouse desliza para fora da bandeja, consulte o código a seguir para obter detalhes;
Como personalizar uma barra de menu do sistema com a altura do elétron?

import { app, Tray, Menu, nativeImage, screen, BrowserWindow,BrowserView,shell } from "electron";
let isLeave = true; // 存储鼠标是否离开托盘的状态
tray.on('mouse-move', (event: any,point: any) => {
    if( isLeave == true ) { // 从其他地方第一次移入菜单时,开始显示菜单页,然后在菜单内移动时不重复再显示菜单
        menuWin.show();
    }
    isLeave = false;
    checkTrayLeave();
});
/**
 * 检查鼠标是否从托盘离开
 */
checkTrayLeave() {
    clearInterval(this.leaveInter)
    this.leaveInter = setInterval(() => {
        let trayBounds = tray.getBounds();
        let point = screen.getCursorScreenPoint();
        // 判断是否再托盘内
        if(!(trayBounds.x < point.x && trayBounds.y < point.y && point.x < (trayBounds.x + trayBounds.width) && point.y < (trayBounds.y  + trayBounds.height))){
            // 触发 mouse-leave
            clearInterval(this.leaveInter);
            menuWin.hide(); // 隐藏菜单栏
            isLeave = true;
        } else {
            console.log('isOn');
        }
    }, 100)
},

2. Como controlar a posição da janela

De acordo com o código da etapa anterior, tray.getBounds () pode ser usado para obter as informações de posição do ícone da bandeja. Vamos primeiro supor que a altura e a largura de nossa barra de menu são 200

let trayBounds = this.appTray.getBounds();
if(!params.x) {
    params.x = trayBounds.x - ( 200 / 2)
}
if(!params.y) {
    params.y = trayBounds.y - params.height;
}
this.menuWin.setBounds(params);

Quando esta etapa é concluída, basicamente quando o mouse desliza para dentro e para fora do ícone da bandeja, ele controla a exibição e ocultação da barra de menu; mas encontraremos um problema, quando deslizarmos o mouse para a janela da barra de menu, ele ficará oculto A barra de menu, você não pode fazer nada assim. Portanto, quando identificamos a posição da bandeja na primeira etapa, devemos desenhar toda a janela da barra de menu na faixa normal de deslizamento da bandeja do sistema:

/**
 * 检查鼠标是否从托盘离开
 */
checkTrayLeave() {
    clearInterval(this.leaveInter)
    this.leaveInter = setInterval(() => {
        let trayBounds = tray.getBounds();
        let point = screen.getCursorScreenPoint();
        // 判断是否再托盘内
        if(!(trayBounds.x < point.x && trayBounds.y < point.y && point.x < (trayBounds.x + trayBounds.width) && point.y < (trayBounds.y  + trayBounds.height))){
             // 判断是否在弹出菜单内
             let menuBounds = this.menuWin.getBounds()
             if(menuBounds.x < point.x && menuBounds.y < point.y && point.x < (menuBounds.x + menuBounds.width) && point.y < (menuBounds.y  + menuBounds.height)) {
                 console.log('isOnMenupage');
                 return ;
             }
             // 触发 mouse-leave
             clearInterval(this.leaveInter);
             menuWin.hide(); // 隐藏菜单栏
             isLeave = true;
        } else {
            console.log('isOn');
        }
    }, 100)
},

Resumindo

Basicamente, todo o esquema de personalização da barra de menus do sistema é provavelmente um tal processo, mas esse esquema também é limitado a sistemas Windows e Mac, a compatibilidade com Linux realmente não pode ser feita, a maioria das APIs não oferece suporte a sistemas Linux.

Acho que você gosta

Origin blog.51cto.com/15024210/2582577
Recomendado
Clasificación