电子遥控器(关闭、最小化等)不起作用(无法读取未定义的 属性 'getCurrentWindow')

Electron Remote (Close, Minimize etc) not work (Cannot read property 'getCurrentWindow' of undefined)

我正在尝试在 Electron JS 应用程序的无框架 window 上添加关闭和最小化按钮。但无论如何它都不起作用。它总是显示“无法读取未定义的 属性 'getCurrentWindow'”错误。这是我的代码:

const {remote} = require('electron');

document.getElementById('minimize').onclick = function() {
    var window = remote.getCurrentWindow();
    window.minimize();
}

document.getElementById('close').onclick = function() {
    var window = remote.getCurrentWindow();
    window.close();
}

我还在 main.js 中添加了 webPreferences: {nodeIntegration: true}。

win = new BrowserWindow({width: 990, height: 660, title: "Okkhor52 Tools", show: false, resizable: false, frame: false, webPreferences: {nodeIntegration: true}});

请给我一个解决方案,我试图在很多地方找到这个问题的解决方案,但我没有得到确切的解决方案。

解决方法很简单。只需在 main.js.

中的 BrowserWindow 中添加 webPreferences: {enableRemoteModule: true}
win = new BrowserWindow({
    width: 990, 
    height: 660,
    title: "Okkhor52 Tools", 
    resizable: false, 
    frame: false, 
    webPreferences: {
        nodeIntegration: true, 
        enableRemoteModule: true
    }
}); 

enableRemoteModule: true旁边你需要在webPreference中添加nodeIntegration: true,否则如果你从其他人的javascript调用electron(像这样const {remote} = require('electron');)它将不起作用.

如果您已经将 enableRemoteModule 设置为 true 但仍然遇到此问题,很可能是因为您需要 the remote module,或者需要一个需要它的文件 里面主要流程,至少我是这样的。远程模块在主进程中不是必需的,仅用于渲染器进程。

如果您在主进程中需要或需要另一个使用 require("electron").remote.getCurrentWindow() 的 javascript 文件,那么您将收到此错误。

通过不以任何方式在主进程中包含该代码来简单地解决这个问题。

其实从安全的角度,我建议你应该使用:

win = new BrowserWindow({
width: 990, 
height: 660,
title: "Okkhor52 Tools", 
resizable: false, 
frame: false, 
webPreferences: {
    nodeIntegration: false, //default 
    enableRemoteModule: true,
    preload: path.join(__dirname, 'preload.js')
}

}); 并将你的js代码放入'preload.js'.

根据官方文档Disable the Node.js integration in all renderers that display remote content,nodeIntergration: true 非常危险。

根据this article we shouldn't use "remote" at all. The better way is to communicate with the renderer through Sending Messages

首先,您需要 WindowNodeHandlers class 来调用 BrowserWindow maximize/unmaximize 操作并更新 isMaximized 标志:

class WindowNodeHandlers {
  ipcMain.on('maximize', () => {
    BrowserWindow.getFocusedWindow()?.maximize();
  });

  ipcMain.on('unmaximize', () => {
    BrowserWindow.getFocusedWindow()?.unmaximize();
  });

  ipcMain.on('isMaximized', (event) => {
    event.returnValue = BrowserWindow.getFocusedWindow()?.isMaximized();
  });
}

然后创建 ElectronWindowApi class 以在渲染器和主进程之间进行通信:

class ElectronWindowApi implements MainWindowApi {
  maximize(): void {
   ipcRenderer.send('maximize');
  }

  unmaximize(): void {
   ipcRenderer.send('unmaximize');
  }

  isMaximized(): boolean {
   return ipcRenderer.sendSync('isMaximized') as boolean;
  }
 }

之后,在您的 createWindow 函数中创建 WindowNodeHandlers 实例并为这些事件添加侦听器,这些事件会将消息发送回渲染器进程:

const createWindow = async () => {
 ...
 new WindowNodeHandlers();

 mainWindow.on('maximize', () =>
   mainWindow?.webContents.send('window-maximized')
 );

 mainWindow.on('unmaximize', () =>
   mainWindow?.webContents.send('window-unmaximized')
 );
}

您应该做的最后一件事 - 为这些消息添加处理程序并使用 ElectronWindowApi 在渲染器端调用 maximize/unmaximize 操作:

...
const windowApi = new ElectronWindowApi();
const [isMaximized, setIsMaximized] = useState(windowApi.isMaximized());
const onMaximized = () => setIsMaximized(true);
const onRestore = () => setIsMaximized(false);

const toggleMaximize = () => {
  isMaximized ? windowApi.unmaximize() : windowApi.maximize();
};

useEffect(() => {
  ipcRenderer.on('window-maximized', onMaximized);
  ipcRenderer.on('window-unmaximized', onRestore);
}, []);

return (
   <IconButton
      aria-label={isMaximized ? 'minimize' : 'maximize'}
      onClick={toggleMaximize}
    >
      {isMaximized ? (
        <SvgIcon
          component={MinimizeWindowIcon}
        />
      ) : (
        <SvgIcon
          component={MaximizeWindowIcon}
        />
      )}
    </IconButton>
)
...