• 09.《Electron 跨平台开发实战》- chapter09-tray模块


    项目代码

    https://github.com/electron-in-action/clipmaster

    创建Tray

    • main.js
    const path = require('path');
    const { app, Menu, Tray } = require('electron');
    let tray = null;
    
    app.on('ready', () => {
        tray = new Tray(path.join(__dirname, 'Icon.png'));
        if (process.platform === 'win32') { //windows系统
            tray.on('click', tray.popUpContextMenu);
        }
    
        if (app.dock) { //macOS系统
            app.dock.hide(); //隐藏Dock图标
        }
    
        const menu = Menu.buildFromTemplate([
            {
                label: '退出',
                // click() {
                //     app.quit();
                // }
                click: () => {
                    app.quit();
                }
            }
        ]);
    
        tray.setToolTip('Clipmaster');
        tray.setContextMenu(menu);
    });
    

    要点解析

    tary基本设置

    tray = new Tray(path.join(__dirname, 'Icon.png'));

    tray.setToolTip('Clipmaster');

    tray.setContextMenu(menu);

    为maxOS和window 选择不同的图标

    const getIcon = () => {
        // if (process.platform === 'win32') {
        //     return 'icon-light@2x.ico';
        // }
    
        if (systemPreferences.isDarkMode()) { //maxOS系统是否处于深色模式
            return 'icon-light@2x.png';
        }
    
        return 'icon-dark.png';
    };
    
    ...
       tray = new Tray(path.join(__dirname, getIcon()));
    
    

    将剪切项放入内存

    const { ..., clipboard  } = require('electron'); //剪切板模块
    
    app.on('ready', () => {
        updateMenu();//tray.setContextMenu(menu);
    });
    
    const updateMenu = () => {
        const menu = Menu.buildFromTemplate([
            {
                label: 'Create New Clipping',
                click() { addClipping(); },
                accelerator: 'CommandOrControl+Shift+C'
            },
            { type: 'separator' },
            ...clippings.slice(0, 10).map(createClippingMenuItem),
            { type: 'separator' },
            {
                label: 'Quit',
                click() { app.quit(); },
                accelerator: 'CommandOrControl+Q'
            }
        ]);
        tray.setContextMenu(menu);
    }
    
    const addClipping = () => {
        const clipping = clipboard.readText();  //读取剪切项
        if (clippings.includes(clipping)) return;
        clippings.unshift(clipping);
        updateMenu();
        return clipping;
    };
    
    
    const createClippingMenuItem = (clipping, index) => {
        return {
            label: clipping.length > 20 ? clipping.slice(0, 20) + '…' : clipping,
            click() { clipboard.writeText(clipping); }, // 写入剪切板
            accelerator: `CommandOrControl+${index}`    //快捷键 递增
        };
    };
    
    

    要点解析

    const { ..., clipboard } = require('electron'); //剪切板模块

    读取剪切项 const clipping = clipboard.readText();

    写入剪切板 clipboard.writeText(clipping);

    js 3个点:扩展运算符

    var number = [1,2,3,4,5,6]
    console.log(...number) //1 2 3 4 5 6
    

    http://www.fly63.com/article/detial/8155

    处理极端项(文字太长):clipping.length > 20 ? clipping.slice(0, 20) + '…' : clipping

    避免添加重复的剪贴项: if (clippings.includes(clipping)) return;

    最新在最前:clippings.unshift(clipping);

    只显示10项:clippings.slice(0, 10).map(createClippingMenuItem)

    注册全局快捷

    accelerator: 'xxx 只有应用处于激活状态才能使用

    globalShortcut 模块

    globalShortcut 模块 提供注册全局快捷键的功能,即使应用处于后台,也能响应快捷键

    注册全局快捷键: globalShortcut.register('xxx', () => { ...});

    • main.js
    app.on('ready', () => {
        ...
        //注册全局快捷键:弹出菜单
        const activationShortcut = globalShortcut.register('CommandOrControl+Alt+C', () => {
            tray.popUpContextMenu();
        });
        if (!activationShortcut) console.error('Global activation shortcut failed to regiester');
    
        //注册全局快捷键:将剪贴项放入内存数组
        const newClippingShortcut = globalShortcut.register('CommandOrControl+Shift+Alt+C', () => {
            const clipping = addClipping();
        });
        if (!newClippingShortcut) console.error('Global new clipping shortcut failed to regiester');
       ...
    

    通知

    使用 Chorminum的Notification API 创建通知

    这种方案使用Chorminum的Notification API 创建通知, 是webAPI,所以只能在渲染进程中使用

    • 创建一个隐藏不显示的BrowseWindow
    • 主进程给消息给渲染进程创建通知

    代码:

    • 创建一个隐藏的BrowserWindow
      index.htm:这个HTML文件唯一的目的就是为了加载渲染进程
    <!DOCTYPE html>
    <html>
        <header>
            <meta charset="UTF-8">
            <title>Clipmaster</title>
        </header>
        <body>
            
        </body>
        <script>
            //这个HTML文件唯一的目的就是为了加载渲染进程
            require('./renderer.js');
        </script>
    </html>
    
    • main.js
    app.on('ready', () => {
    ...
        browserWindow = new BrowserWindow({
            webPreferences: {
                nodeIntegration: true
            },
            show: false
        });
        browserWindow.loadURL(`file://${__dirname}/index.html`);
    ...
        //注册全局快捷键:将剪贴项放入内存数组
        const newClippingShortcut = globalShortcut.register('CommandOrControl+Alt+num8', () => {
            const clipping = addClipping();
            if (clipping) {
                //向渲染进程发送消息,让渲染进程创建通知
                browserWindow.webContents.send('show-notification', '已经添加到剪切板', clipping); 
            }
        });
    
    • renderer.js
    const { ipcRenderer } = require('electron');
    ipcRenderer.on('show-notification', (event, title, body) => {
        const myNotification = new Notification(title, { body: body });
        myNotification.onclick = () => { //点击通知触发click事件
            alert("我知道了");
        }
    });
    

    使用 Electron 的Notification 模块

    主进程也可以向系统发通知

    • main.js
    const { 
       ..., Notification // 通知模块
    } = require('electron');
    
    const updateMenu = () => {
        const menu = Menu.buildFromTemplate([
            {
                label: 'Create New Clipping',
                //click() { addClipping(); },
                click: () => {
                    let clipping = addClipping();
                    //使用Notification模块发送通知
                    let myNotification = new Notification({
                        title: 'Notification模块通知',
                        body: clipping
                    })
                    myNotification.show();//必须调用show才会显示通知
                    myNotification.on('click', () => {
                        console.log('Notification模块通知的点击事件')
                    });
    
                },
    ...
    
    

    macOS单击菜单栏切换图标

       //macOS单击菜单栏切换图标
        tray.setPressedImage(path.join(__dirname, 'icon-light.png'))
    
  • 相关阅读:
    Vue的配置安装与项目创建
    log4j:WARN No appenders could be found for logger
    终于在博客园扎根了
    简单工厂模式
    详解apache防盗链网站图片防盗链方法
    怎样能写好文章标题
    生活需要阿Q精神
    2013个人博客全新起航
    华中师范大学新生网上怎么选宿舍
    华中师范大学2012级新生QQ交流群欢迎加入!
  • 原文地址:https://www.cnblogs.com/easy5weikai/p/13153264.html
Copyright © 2020-2023  润新知