Electron,我怎么能让标题按钮工作呢?

9w11ddsr  于 2023-04-03  发布在  Electron
关注(0)|答案(1)|浏览(152)

我使用frame: false使标题栏消失,然后我试图使按钮的功能从others respond,但它不工作
index.html:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>my app</title>
    <link rel="stylesheet" href="index.css" />

    

  </head>
  <body>
    

    <div class="title-container">
      <img src="res/applogo.png" style="width: 22px; height: 22px;">
      <div style="width: 5px; height: 22px;"></div>
      <p class="title-text">my app - some page</p>
      <a href="#" style="text-decoration: none;"><p class="title-button" id="min-btn">-</p></a>
      <a href="#" style="text-decoration: none;"><p class="title-button" id="max-btn">◻</p></a>
      <a href="#" style="text-decoration: none;"><p class="title-button" id="close-btn">×</p></a>
    </div>
    <div class="application-container">
      ...
    </div>

    <script>
      document.querySelector('button[data-title="Developer Tool"]').addEventListener('click', () => {
        window.open('devTool.html', "_blank", "width=1200,height=714,resizable=false,,autoHideMenuBar=true"); // local file
      })
      const remote = require('electron').remote;

      document.getElementById("min-btn").addEventListener("click", function (e) {
        var window = remote.getCurrentWindow();
        window.minimize(); 
      });
      
      document.getElementById("max-btn").addEventListener("click", function (e) {
        var window = remote.getCurrentWindow();
        if (!window.isMaximized()) {
          window.maximize();          
        } else {
          window.unmaximize();
        }
      });
      
      document.getElementById("close-btn").addEventListener("click", function (e) {
        var window = remote.getCurrentWindow();
        window.close();
      }); 
    </script>
    <script src="index.js"></script>
    
  </body>
</html>

index.js是一个空白文件
我怎样才能使按钮工作?请详细答复,如果你可以,因为我仍然是相当新的JavaScript,谢谢你。如果有什么不清楚,请告诉我下面,我会尽量提供它。

kgsdhlau

kgsdhlau1#

与其他SO Question类似,您需要熟悉以下Electron Browser Window - Instance Methods以获取更多信息。

  • win.minimize()
  • win.maximize()
  • win.restore()
  • win.close()

在创建窗口时,我们告诉窗口它所处的状态。例如:最大化或恢复。这个“状态”通过IPC(通过我们的preload.js脚本)发送到渲染端Javascript,以显示或隐藏正确的最大化/恢复按钮。
在此之后,我们只需要监听渲染端标题栏按钮的点击。点击后,通过IPC向主进程发送一条消息来控制窗口的状态。根据请求(“maximize”或“restore”),通过IPC向渲染进程发送一条消息,以“show”或“hide”(通过CSS display属性)正确的maximize/ restore按钮。
在这里,我们将窗口框架状态设置为false,加载index.html文件,告诉渲染进程(通过IPC)窗口的状态(在本例中恢复),然后最终显示窗口。
main.js(主进程)

// Import required electron modules
const electronApp = require('electron').app;
const electronBrowserWindow = require('electron').BrowserWindow;
const electronIpcMain = require('electron').ipcMain;

// Import required Node modules
const nodePath = require('path');

// Prevent garbage collection
let window;

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

    window.loadFile(nodePath.join(__dirname, 'index.html'))
        // Below boolean value could be retrieved from saved application setting (json file) on start-up
        .then(() => { window.webContents.send('maximised', false); })
        .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('minimise', (event) => {
    window.minimize();
})

electronIpcMain.on('maximise', (event) => {
    window.maximize();
    window.webContents.send('maximised', true);
})

electronIpcMain.on('restore', (event) => {
    window.restore();
    window.webContents.send('maximised', false);
})

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

设置用于管理窗口状态的通道名称。
preload.js(主进程)

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

// White-listed channels
const ipc = {
    'channels': {
        // From render to main
        'send': [
            'minimise',
            'maximise',
            'restore',
            'close'
        ],
        // From main to render
        'receive': [
            'maximised'
        ],
        // From main to render (once)
        'receiveOnce': [],
        // From render to main and back again
        'sendReceive': []
    }
};

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

这个preload.js脚本的用法如下。

/**
 *
 * Main --> Render
 * ---------------
 * Main:    window.webContents.send('channel', data); // Data is optional.
 * Render:  window.ipcRenderer.receive('channel', (data) => { methodName(data); });
 *
 * Main --> Render (Once)
 * ----------------------
 * Main:    window.webContents.send('channel', data); // Data is optional.
 * Render:  window.ipcRenderer.receiveOnce('channel', (data) => { methodName(data); });
 *
 * Render --> Main
 * ---------------
 * Render:  window.ipcRenderer.send('channel', data); // Data is optional.
 * Main:    electronIpcMain.on('channel', (event, data) => { methodName(data); })
 *
 * Render --> Main (Once)
 * ----------------------
 * Render:  window.ipcRenderer.send('channel', data); // Data is optional.
 * Main:    electronIpcMain.once('channel', (event, data) => { methodName(data); })
 *
 * Render --> Main (Value) --> Render
 * ----------------------------------
 * Render:  window.ipcRenderer.invoke('channel', data).then((result) => { methodName(result); });
 * Main:    electronIpcMain.handle('channel', (event, data) => { return someMethod(data); });
 *
 * Render --> Main (Promise) --> Render
 * ------------------------------------
 * Render:  window.ipcRenderer.invoke('channel', data).then((result) => { methodName(result); });
 * Main:    electronIpcMain.handle('channel', async (event, data) => {
 *              return await myPromise(data)
 *                  .then((result) => { return result; })
 *          });
 *
 * Main:    function myPromise(data) { return new Promise((resolve, reject) => { ... }); }
 *
 */

最后,让我们监听并发送消息到主进程(通过我们的preload.js脚本)来管理窗口状态。
index.html(渲染进程)

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>my app</title>
        <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';"/>
    </head>

    <body style="margin: 0; padding: 0;">

        <!-- Simple use of flexbox styling + prevent user from selecting title bar contents -->
        <div style="display: flex; justify-content: space-between; padding: 0.25em; background-color: grey; -webkit-user-select: none;">

            <!-- Add title bar drag functionality by using "-webkit-app-region: drag;" -->
            <span style="flex: 1 0 auto; -webkit-app-region: drag;">
                <img src="" alt="logo" style="width: 22px; height: 22px;">
                <span class="title-text">My App - Some Page</span>
            </span>

            <!-- Prevent title bar dragging by buttons by using "-webkit-app-region: no-drag;" -->
            <span style="flex: 0 1 auto; -webkit-app-region: no-drag;">
                <input type="button" id="minimise_button" value="-">
                <input type="button" id="maximise_button" value="◻">
                <input type="button" id="restore_button" value="R">
                <input type="button" id="close_button" value="×">
            </span>
        </div>

        <div class="application-container">...</div>
    </body>

    <script>
        // Declare these elements as we use them more than once
        let maximise_button = document.getElementById('maximise_button');
        let restore_button = document.getElementById('restore_button');

        // Minimise button functionality
        document.getElementById('minimise_button').addEventListener('click', () => {
            window.ipcRenderer.send('minimise');
        });

        // Maximise button functionality
        maximise_button.addEventListener('click', () => {
            window.ipcRenderer.send('maximise');
        });

        // Restore button functionality
        restore_button.addEventListener('click', () => {
            window.ipcRenderer.send('restore');
        });

        // Close button functionality
        document.getElementById('close_button').addEventListener('click', () => {
            window.ipcRenderer.send('close');
        });

        // Toggle css "display" attribute of maximise & restore buttons depending on state of window
        window.ipcRenderer.receive('maximised', (state) => {
            maximise_button.style.display = (state) ? 'none' : 'inline-block';
            restore_button.style.display = (state) ? 'inline-block' : 'none';
        });
    </script>
</html>

相关问题