1

I want to Close, Minimize and Maximize my electron application from Javascript. I tried it with this code. It worked for maximize and close but sometimes it's not working.

const { app } = require("electron");
const remote = require("electron").remote;

function closeApplication() {
    window.close().method;
}

function maximizeWindow() {
    // win.maximize();
    // window.maximize();
    window.moveTo(0, 0);
    window.resizeTo(screen.width, screen.height);
}

function minimizeWindow() {
    let window = remote.getCurrentWindow();
    window.minimize();
}

Can anyone help me

Vidu
  • 33
  • 1
  • 7
  • 1
    Welcome to Stackoverflow. Could you please elaborate more about "Sometimes its not working"? – Mahesh Jan 03 '22 at 13:29
  • A user event might be needed to execute those functions for security reasons. Also the Window.close() function for example can only be executed on windows that where opened by the same script with Window.open(). Same condition for Window.resizeTo(). – Mark Baijens Jan 03 '22 at 14:06

1 Answers1

0

Having Electron manage the minimising, maximising, restoring and closing of your window in the main process is recommended.

See the below Browser Window - Instance Methods for more information.


To implement this functionality, use of a simple preload.js script configured to transmit data via the use of channel names between the main process and render process(es) can be used.

Note the use of the channel names window:minimize, window:maximize, window:restore and window:close. You can use any channel name you like.

preload.js (main process)

// Import the necessary Electron components.
const contextBridge = require('electron').contextBridge;
const ipcRenderer = require('electron').ipcRenderer;

// White-listed channels.
const ipc = {
    'render': {
        // From render to main.
        'send': [
            'window:minimize', // Channel names
            'window:maximize',
            'window:restore',
            'window:close'
        ],
        // From main to render.
        'receive': [],
        // From render to main and back again.
        'sendReceive': []
    }
};

// Exposed protected methods in the render process.
contextBridge.exposeInMainWorld(
    // Allowed 'ipcRenderer' methods.
    'ipcRender', {
        // From render to main.
        send: (channel, args) => {
            let validChannels = ipc.render.send;
            if (validChannels.includes(channel)) {
                ipcRenderer.send(channel, args);
            }
        },
        // From main to render.
        receive: (channel, listener) => {
            let validChannels = ipc.render.receive;
            if (validChannels.includes(channel)) {
                // Deliberately strip event as it includes `sender`.
                ipcRenderer.on(channel, (event, ...args) => listener(...args));
            }
        },
        // From render to main and back again.
        invoke: (channel, args) => {
            let validChannels = ipc.render.sendReceive;
            if (validChannels.includes(channel)) {
                return ipcRenderer.invoke(channel, args);
            }
        }
    }
);

Further, use of the above preload.js script can be used as shown below.

/**
 * Render --> Main
 * ---------------
 * Render:  window.ipcRender.send('channel', data); // Data is optional.
 * Main:    electronIpcMain.on('channel', (event, data) => { methodName(data); })
 *
 * Main --> Render
 * ---------------
 * Main:    windowName.webContents.send('channel', data); // Data is optional.
 * Render:  window.ipcRender.receive('channel', (data) => { methodName(data); });
 *
 * Render --> Main (Value) --> Render
 * ----------------------------------
 * Render:  window.ipcRender.invoke('channel', data).then((result) => { methodName(result); });
 * Main:    electronIpcMain.handle('channel', (event, data) => { return someMethod(data); });
 *
 * Render --> Main (Promise) --> Render
 * ------------------------------------
 * Render:  window.ipcRender.invoke('channel', data).then((result) => { methodName(result); });
 * Main:    electronIpcMain.handle('channel', async (event, data) => {
 *              return await promiseName(data)
 *                  .then(() => { return result; })
 *          });
 */

In the main.js script, let's listen for use of the channel name(s) and when detected, modify the window via the corresponding instance method(s).

main.js (main process)

const electronApp = require('electron').app;
const electronBrowserWindow = require('electron').BrowserWindow;
const electronIpcMain = require('electron').ipcMain;

const nodePath = require('path');

let window;

function createWindow() {
    const window = new electronBrowserWindow({
        x: 0,
        y: 0,
        width: 800,
        height: 600,
        show: false,
        webPreferences: {
            nodeIntegration: false,
            contextIsolation: true,
            preload: nodePath.join(__dirname, 'preload.js')
        }
    });

    window.loadFile('index.html')
        .then(() => { window.show(); });

    return window;
}

electronApp.on('ready', () => {
    window = createWindow();
});

electronApp.on('window-all-closed', () => {
    if (process.platform !== 'darwin') {
        electronApp.quit();
    }
});

electronApp.on('activate', () => {
    if (electronBrowserWindow.getAllWindows().length === 0) {
        createWindow();
    }
});

// ---

electronIpcMain.on('window:minimize', () => {
    window.minimize();
})

electronIpcMain.on('window:maximize', () => {
    window.maximize();
})

electronIpcMain.on('window:restore', () => {
    window.restore();
})

electronIpcMain.on('window:close', () => {
    window.close();
})

And finally, using event listeners, lets listed for click events of buttons to send a message along the correct channel (name).

index.html (render process)

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Electron Test</title>
    </head>

    <body>
        <input type="button" id="minimize" value="minimise">
        <input type="button" id="maximize" value="maximise">
        <input type="button" id="restore" value="restore">
        <input type="button" id="close" value="close">
    </body>

    <script>
        document.getElementById('minimize').addEventListener('click', () => {
            window.ipcRender.send('window:minimize');
        });

        document.getElementById('maximize').addEventListener('click', () => {
            window.ipcRender.send('window:maximize');
        });

        document.getElementById('restore').addEventListener('click', () => {
            window.ipcRender.send('window:restore');
        });

        document.getElementById('close').addEventListener('click', () => {
            window.ipcRender.send('window:close');
        });
    </script>
</html>
midnight-coding
  • 2,857
  • 2
  • 17
  • 27
  • I did the exact same thing except the become a
    . it says an error occur which is window is not defined. How can I fix that?
    – Ichor Dragon Oct 25 '22 at 07:48
  • @IchorDragon Are you using a preload script and is it being loaded in your window creation function? Do you have contextIsolation set to `true`? – midnight-coding Oct 25 '22 at 10:22
  • I do add preload script in at first, now I tried making the contextIsolation into true but still didn't work, it says that the main.js, the window in `window.minimize` (and others) isn't defined – Ichor Dragon Oct 26 '22 at 08:59
  • @IchorDragon Best to ask a (new) question with your `main.js`, `preload.js` and `index.html` files included + what your error is. – midnight-coding Oct 26 '22 at 11:51
  • I did one, here is it https://stackoverflow.com/questions/74243344/electron-how-to-make-my-custom-title-button-work – Ichor Dragon Oct 29 '22 at 06:44