admin管理员组

文章数量:1134549

I want my Electron.js application to live on system tray and whenever the user wants to do something they can restore from the system tray do something and minimize/close it back to system tray. How do i do that?

I've seen the tray section from the documentation but doesn't help much to achieve what i want.

Here is what i got so far on the main.js file

var application = require('app'),
    BrowserWindow = require('browser-window'),
    Menu = require('menu'), 
    Tray = require('tray'); 
application.on('ready', function () {
    var mainWindow = new BrowserWindow({
        width: 650,
        height: 450,
        'min-width': 500,
        'min-height': 200,
        'accept-first-mouse': true,
        // 'title-bar-style': 'hidden',
        icon:'./icon.png'
    });
    mainWindow.loadUrl('file://' + __dirname + '/src/index.html');
    mainWindow.on('closed', function () {
        mainWindow = null;
    });
    mainWindow.setMenu(null);

    var appIcon = null;
    appIcon = new Tray('./icon-resized.png');
    var contextMenu = Menu.buildFromTemplate([
        { label: 'Restore', type: 'radio' }
    ]);
    appIcon.setToolTip('Electron.js App');
    appIcon.setContextMenu(contextMenu);
});

UPDATE:

I found this menubar repo, but it won't work as expected on linux.

I want my Electron.js application to live on system tray and whenever the user wants to do something they can restore from the system tray do something and minimize/close it back to system tray. How do i do that?

I've seen the tray section from the documentation but doesn't help much to achieve what i want.

Here is what i got so far on the main.js file

var application = require('app'),
    BrowserWindow = require('browser-window'),
    Menu = require('menu'), 
    Tray = require('tray'); 
application.on('ready', function () {
    var mainWindow = new BrowserWindow({
        width: 650,
        height: 450,
        'min-width': 500,
        'min-height': 200,
        'accept-first-mouse': true,
        // 'title-bar-style': 'hidden',
        icon:'./icon.png'
    });
    mainWindow.loadUrl('file://' + __dirname + '/src/index.html');
    mainWindow.on('closed', function () {
        mainWindow = null;
    });
    mainWindow.setMenu(null);

    var appIcon = null;
    appIcon = new Tray('./icon-resized.png');
    var contextMenu = Menu.buildFromTemplate([
        { label: 'Restore', type: 'radio' }
    ]);
    appIcon.setToolTip('Electron.js App');
    appIcon.setContextMenu(contextMenu);
});

UPDATE:

I found this menubar repo, but it won't work as expected on linux.

Share Improve this question edited Jun 16, 2016 at 8:02 miqe asked Jun 15, 2016 at 7:27 miqemiqe 3,3693 gold badges30 silver badges37 bronze badges
Add a comment  | 

8 Answers 8

Reset to default 122

I actually figured it out a long time ago but for folks who encounter the same problem here is one way you could achieve minimizing to tray and restoring from tray. The trick is to catch the close and minimize events.

var BrowserWindow = require('browser-window'),

var mainWindow = new BrowserWindow({
    width: 850,
    height: 450,
    title: "TEST",
    icon:'./icon.png'
});

mainWindow.on('minimize',function(event){
    event.preventDefault();
    mainWindow.hide();
});

mainWindow.on('close', function (event) {
    if(!application.isQuiting){
        event.preventDefault();
        mainWindow.hide();
    }

    return false;
});

and restoring from Tray

var contextMenu = Menu.buildFromTemplate([
    { label: 'Show App', click:  function(){
        mainWindow.show();
    } },
    { label: 'Quit', click:  function(){
        application.isQuiting = true;
        application.quit();
    } }
]);

Addition to above answers - isQuiting flag is worth setting at app' before-quit callback, too. This way the application will be closed properly if requested by the OS or user some other way, e.g. via Macos Dock taskbar' quit command. Complete Typescript-friendly snippet:

import {app, BrowserWindow, Tray, Menu} from 'electron';
import * as path from 'path';

let window;
let isQuiting;
let tray;

app.on('before-quit', function () {
  isQuiting = true;
});

app.on('ready', () => {
  tray = new Tray(path.join(__dirname, 'tray.png'));

  tray.setContextMenu(Menu.buildFromTemplate([
    {
      label: 'Show App', click: function () {
        window.show();
      }
    },
    {
      label: 'Quit', click: function () {
        isQuiting = true;
        app.quit();
      }
    }
  ]));

  window = new BrowserWindow({
    width: 850,
    height: 450,
    show: false,
  });

  window.on('close', function (event) {
    if (!isQuiting) {
      event.preventDefault();
      window.hide();
      event.returnValue = false;
    }
  });
});

I updated the code with a scenario if you want to show icon on your system tray all the time until you don't quit the application

var { app, BrowserWindow, Tray, Menu } = require('electron')
var path = require('path')
var url = require('url')
var iconpath = path.join(__dirname, 'user.ico') // path of y
var win
function createWindow() {
    win = new BrowserWindow({ width: 600, height: 600, icon: iconpath })

    win.loadURL(url.format({
        pathname: path.join(__dirname, 'index.html'),
    }))

    var appIcon = new Tray(iconpath)

    var contextMenu = Menu.buildFromTemplate([
        {
            label: 'Show App', click: function () {
                win.show()
            }
        },
        {
            label: 'Quit', click: function () {
                app.isQuiting = true
                app.quit()
            }
        }
    ])

    appIcon.setContextMenu(contextMenu)

    win.on('close', function (event) {
        win = null
    })

    win.on('minimize', function (event) {
        event.preventDefault()
        win.hide()
    })

    win.on('show', function () {
        appIcon.setHighlightMode('always')
    })

}

app.on('ready', createWindow)

A better way than using flags and for those who do not want to change the minimize behavior :

just normally hide the window on close event using mainWindow.hide()

mainWindow.on('close', function (event) {
    event.preventDefault();
    mainWindow.hide();
});

then call mainWIndow.destroy() to force close the window. It also guarantees to execute the closed event handler.

From the documentation:

Force closing the window, the unload and beforeunload event won't be emitted for the web page, and close event will also not be emitted for this window, but it guarantees the closed event will be emitted.

var contextMenu = Menu.buildFromTemplate([
    { label: 'Show App', click:  function(){
        mainWindow.show();
    } },
    { label: 'Quit', click:  function(){
        mainWindow.destroy();
        app.quit();
    } }
]);

This was tagged with NW.js, and since all the other answers are for Electron I thought I'd show off how much easier everything always is in NW.js. There is a simple demo repo set up right here:

  • https://github.com/nwutils/nw-tray-example

Just download that and run npm install && npm start.

I share my Sketch, on minimize hide on taskbar icon, menu options rigth-click icon to restore/close. using websocket/http server..

//const {app, BrowserWindow} = require('electron');
const {app, BrowserWindow, Tray, Menu} = require('electron');
const myip = require('quick-local-ip');
const express = require('express');
const WebSocket = require('ws');
const bodyParser = require('body-parser');
const path = require('path')
// Config
const Config = {
    http_port: '8080',
    socket_port: '3030'
};

var iconpath = path.join(__dirname, 'rfid.png') // path of y

// Http server
const _app = express();
const server = require('http').Server(_app);
server.listen(Config.http_port);

// WSS server
const wss = new WebSocket.Server({port: Config.socket_port});

// Console print
console.log('[SERVER]: WebSocket on: ' + myip.getLocalIP4() + ':' + Config.socket_port); // print websocket ip address
console.log('[SERVER]: HTTP on: ' + myip.getLocalIP4() + ':' + Config.http_port); // print web server ip address

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow;

let window;
let isQuiting;
let tray;

function createWindow() {
    mainWindow = new BrowserWindow({
        width: 1200,
        height: 800,
        acceptFirstMouse: true,
        autoHideMenuBar: false,
        useContentSize: true,
    });

    var appIcon = new Tray(iconpath);

    // mainWindow.loadURL('index.html')
    mainWindow.loadURL('http://localhost:8080');
    mainWindow.focus();
    // mainWindow.setFullScreen(true);

    // Open the DevTools.
    mainWindow.webContents.openDevTools();

    var contextMenu = Menu.buildFromTemplate([
        {
            label: 'Show App', click: function () {
                mainWindow.show()
            }
        },
        {
            label: 'Quit', click: function () {
                app.isQuiting = true
                app.quit()
            }
        }
    ])

    appIcon.setContextMenu(contextMenu)

    // Emitted when the window is closed.
    mainWindow.on('close', function (event) {
        mainWindow = null
    });

    mainWindow.on('minimize', function (event) {
        event.preventDefault()
        mainWindow.hide()
    });

    mainWindow.on('show', function () {
        appIcon.setHighlightMode('always')
    })
}

app.on('ready', createWindow)

// Quit when all windows are closed.
app.on('window-all-closed', function () {
    // On OS X it is common for applications and their menu bar
    // to stay active until the user quits explicitly with Cmd + Q
    if (process.platform !== 'darwin') {
        app.quit()
    }
})

app.on('activate', function () {
    // On OS X it's common to re-create a window in the app when the
    // dock icon is clicked and there are no other windows open.
    if (mainWindow === null) {
        createWindow()
    }
})

/**
 * EXPRESS
 */
_app.use(bodyParser.urlencoded({
    extended: false
}));

_app.use('/assets', express.static(__dirname + '/www/assets'))

_app.get('/', function (req, res) {
    res.sendFile(__dirname + '/www/index.html');
});

/**
 * WEBSOCKET
 */
wss.getUniqueID = function () {
    function s4() {
        return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
    }

    return s4() + s4() + '-' + s4();
};

wss.on('connection', function connection(ws, req) {
    ws.id = wss.getUniqueID();
    console.log('[SERVER]: Client Connected. ID=', ws.id);

    ws.on('close', function close() {
        console.log('[SERVER]: Client disconnected.');
    });

    ws.on('message', function incoming(recieveData) {
        console.log('[SERVER] Message:', recieveData);

        // Example use
        // send(recieveData);

        sendAll(recieveData);
    });

    // Send back to client
    function send(data) {
        data = JSON.stringify(data);
        ws.send(data);
    }

    // Send to all clients
    function sendAll(data) {
        data = JSON.stringify(data);

        wss.clients.forEach(function each(client) {
            client.send(data);
        });
    }
});

My solution:

let ownIsHidden: boolean;

mainWindow.on('show', () => {
    ownIsHidden = false;
  });

mainWindow.on('hide', function () {
    ownIsHidden = true;
  });

tray.on('mouse-down', () => {
    if (ownIsHidden) {
      mainWindow?.show();
    } else {
      mainWindow?.hide();
    }
  });

Try minimize event instead of hide.

var BrowserWindow = require('browser-window'),

var mainWindow = new BrowserWindow({
    width: 850,
    height: 450,
    title: "TEST",
    icon:'./icon.png'
});

mainWindow.on('minimize',function(event){
    event.preventDefault();
    mainWindow.minimize();
});

mainWindow.on('close', function (event) {

  event.preventDefault();
  mainWindow.minimize();
    return false;
});

This worked for me. hide() was closing the window.

本文标签: