This issue mainly introduces the opening of the expansion screen and the message communication between the two Windows.

Expand the screen

In the window launch section we enclose a createWindow, which is used to create a window. The extension screen is also a window, but we put it on the corresponding external screen depending on how many screens there are.

Rendering process

We add a button to the renderer process that sends the extended screen action (open or hide) to the main process when clicked.

<a-button type="primary" @click="openScreen"> </a-button> const state = reactive({open: true, message: '' }) async function openScreen() { await window.ipcRenderer.invoke('win-subScreen', { open: state.open, path: '#/subScreen' }) state.open = ! state.open }Copy the code

The main process

Once the main process receives it, it fetches the array of the current window (with several displays) via screen.getalldisplays (), and then fetches information about our external screen based on externalDisplay. Similarly, we create a new window with createWindow. We passed a path to the renderer before, and this path is the page we want to display in the extension screen. Note that the value returned by createWindow needs to be stored in a global variable. If it is a local variable, it will be destroyed after the function completes, so the window will be destroyed. The global assignment that we’re going to do is the same as the global assignment that you’re going to do.

global.js global.tray = null global.willQuitApp = false global.envConfig = {} global.sharedObject = { win: '', subScreen: '' } export default global import { ipcMain, app, screen } from 'electron' import global from '.. /config/global' import createWindow from './createWindow' import path from 'path' const win = global.sharedObject.win ipcMain.handle('win-subScreen', (_, data) => { if (data.open) { const displays = screen.getAllDisplays() const mainBounds = win.getNormalBounds() const externalDisplay = displays.find((display) => { return display.bounds.x ! == 0 || display.bounds.y ! == 0 }) if (externalDisplay) { if (global.sharedObject.subScreen) { global.sharedObject.subScreen.show() } else { Global. SharedObject. SubScreen = createWindow ({frame: false, show: false, the parent: win, / / win is the main window fullscreen: true, webPreferences: { webSecurity: false, contextIsolation: false, enableRemoteModule: true, nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION, plugins: true, preload: path.join(__dirname, 'preload.js'), devTools: false }, x: mainBounds.x < 0 && Math.abs(mainBounds.x) > (win.getContentSize()[0] / 2) ? 0 : externalDisplay.bounds.x, y: externalDisplay.bounds.y }, data.path, `index.html${data.path}`) global.sharedObject.subScreen.once('ready-to-show', () => { global.sharedObject.subScreen.show() }) global.sharedObject.subScreen.on('closed', () = > {global. SharedObject. SubScreen = null})}} else {the console. The log (' not detected expansion screen ')}} else { global.sharedObject.subScreen && global.sharedObject.subScreen.destroy() } })Copy the code

For example, if we have two screens, 1 and 2, then our main window and extension screen should be in different positions. For example, if we have two screens, 1 and 2, our main window and extension screen should be in different positions. If our main window is at 1, our extension screen should be opened at 2. If the position is the same, since our extension screen is set to be full-screen, the main window will be blocked at this time. If no shortcut key is set to close, the extension screen will not be closed, so we have the following treatment.

Const mainBounds = win.getNormalBounds() mainBounds main window information, if more than half of the main window is on the secondary screen, then we consider the main window to be on the secondary screen, then the extended screen should be on the main screen, otherwise it should be on the secondary screen. x: mainBounds.x < 0 && Math.abs(mainBounds.x) > (win.getContentSize()[0] / 2) ? 0 : externalDisplay.bounds.xCopy the code

Window communication

Generally speaking, there are two ways to communicate between the Windows of electorn.

  1. Window A renderer sends A message to the main process, which then sends the message to window B’s renderer, using the main process as A relay.
  2. Window A through window B in the rendering processWebContents.idSend the message directly to window B.

Communication mode

Here are some common ways to communicate

Ipcrenderer. invoke: The renderer sends a message to the main process, which is a promise to retrieve the return value of ipcmain. handle in resolve: Invoke IpCrenderer. send: The renderer sends a message to the main process. ipcmain. on: The renderer receives a message sent by ipCrenderer. on: the renderer receives a message sent by ipCrenderer. on: Send: the main process sends a message to the renderer. IpcRenderer. SendTo: You can use webContentsId to send the message directly to the corresponding renderer windowCopy the code

So let’s implement 1,2 here

Rendering process

Remote.getglobal (‘sharedObject’).subscreen is the window we extended the screen earlier. TransferSub is our plan 1, directSub is plan 2.

div class="subMessage"> <a-textarea v-model:value="state.message" :auto-size="{ minRows: 2, maxRows: 5}" /> <a-button type="primary" :disabled="state.message.length === 0" @click="transferSub"> <a-button > <a-button Type ="primary" :disabled="state.message.length === 0" @click="directSub"> </a-button> </div> import { defineComponent, reactive, onMounted, onUnmounted, getCurrentInstance } from 'vue' const { remote } = require('electron') const state = reactive({ open: true, message: '' }) const { proxy } = getCurrentInstance() const { $message } = proxy function transferSub() { window.ipcRenderer.invoke('win-subScreen-message', state.message) } function directSub() { const subScreen = remote.getGlobal('sharedObject').subScreen if (subScreen) { window.ipcRenderer.sendTo(subScreen.webContents.id, 'main-subScree', state.message) } } onMounted(() => { window.ipcRenderer.on('subScree-main', (_event, data) => { $message.success(data) }) }) onUnmounted(() => { window.ipcRenderer.removeListener('subScree-main') })Copy the code

The main process

Go ahead and send the message to the extension screen with webcontents.send

ipcMain.handle('win-subScreen-message', (_, data) => {
  if (global.sharedObject.subScreen) {
    global.sharedObject.subScreen.webContents.send('renderer-subScreen-message', data)
  }
})
Copy the code

Expand screen information receiving and sending

Here we directly listen for messages forwarded and messages sent directly, and then directly notify the main window message.

<template> <div class="subScreen">{{ state.message }}</div> </template> <script> import { defineComponent, reactive, onMounted, onUnmounted } from 'vue' const { remote } = require('electron') export default defineComponent({ setup() { const state =  reactive({ message: '' }) onMounted(() => { const win = remote.getGlobal('sharedObject').win window.ipcRenderer.on('renderer-subScreen-message', (_event, data) => { state.message = data window.ipcRenderer.sendTo(win.webContents.id, 'subScree-main', 'I received a forwarding message ')}) window.ipcrenderer. on(' main-subscree ', (_event, data) => { state.message = data window.ipcRenderer.sendTo(win.webContents.id, 'subScree-main', 'I received directly send information')})}) onUnmounted (() = > {window. IpcRenderer. RemoveListener (' the renderer - subScreen - the message) window.ipcRenderer.removeListener('main-subScree') }) return { state } } }) </script>Copy the code

validation

We open the extension screen and input information in the main window. Click “Send directly” or “send forward” to see whether the display of the extension window is the information we input. The main window displays the notification information of the extension screen.

This series of updates can only be arranged during weekends and off-duty hours. If there are too many contents, the update will be slow. I hope it will be helpful to you

Address: xuxin123.com/electron/ip… This article github address: link