You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Electron.js实现仅显示自身全屏并冻结其他应用(可切换)

Electron 实现考试模式:锁定系统仅允许访问当前应用

我正在用 Electron.js 开发桌面应用,想要实现类似在线考试的效果:用户只能操作这个 Electron 应用,无法打开或切换到其他窗口/应用,而且这个锁定功能可以通过应用内的按钮开启和关闭。我从 AI 助手那里拿到了一段代码,但运行不起来,作为 Electron 新手,不知道该怎么解决。

原代码文件

index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
  <title>Hello World!</title>
</head>

<body>
  <h1>Block Other Applications</h1>
  <button id="blockButton">Block Other Apps</button>

  <script>
    const { ipcRenderer } = require('electron');

    document.getElementById('blockButton').onclick = () => {
      alert('Blocking!')
      ipcRenderer.send('block-apps');
    };
  </script>
</body>

</html>

main.js

const path = require('node:path')

app.whenReady().then(createMainWindow);

ipcMain.on('block-apps', (event) => {
  createOverlayWindow();
});

ipcMain.on('restore-apps', (event) => {
  if (overlayWindow) {
    overlayWindow.close();
    overlayWindow = null;
  }
});

app.on('window-all-closed', () => {
  app.quit();
});

//Code to create an overlay
let mainWindow;
let overlayWindow;

function createMainWindow() {
  mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: false,
    },
  });

  mainWindow.loadFile('index.html');
}

function createOverlayWindow() {
  overlayWindow = new BrowserWindow({
    width: 1920, // Set based on your screen resolution
    height: 1200, // Set based on your screen resolution
    frame: false,
    transparent: true,
    alwaysOnTop: true,
    resizable: false,
    movable: false,
    fullscreen: true,
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: false,
    },
  });

  overlayWindow.loadFile('overlay.html');
}

overlay.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Overlay</title>
  <style>
    body {
      background-color: rgba(0, 0, 0, 0.8);
      color: white;
      display: flex;
      align-items: center;
      justify-content: center;
      height: 100vh;
      font-size: 2em;
    }
  </style>
</head>
<body>
  <div>
    Other applications are blocked.
    <br><br>
    <button id="restoreButton">Restore Access</button>
  </div>

  <script>
    const { ipcRenderer } = require('electron');

    document.getElementById('restoreButton').onclick = () => {
      ipcRenderer.send('restore-apps');
    };
  </script>
</body>
</html>

问题分析与修复方案

原代码无法运行的核心问题是缺少Electron核心模块引入,同时存在逻辑顺序错误和安全隐患。以下是修复后的完整代码:

1. 修复后的 main.js

const { app, BrowserWindow, ipcMain, screen } = require('electron');
const path = require('node:path');

let mainWindow;
let overlayWindow;

// 创建主窗口
function createMainWindow() {
  mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      // 启用预加载脚本,替代不安全的nodeIntegration
      preload: path.join(__dirname, 'preload.js'),
      contextIsolation: true,
      nodeIntegration: false
    },
    alwaysOnTop: false
  });

  mainWindow.loadFile('index.html');
}

// 创建全屏覆盖层窗口
function createOverlayWindow() {
  const primaryDisplay = screen.getPrimaryDisplay();
  const { width, height } = primaryDisplay.workAreaSize;

  overlayWindow = new BrowserWindow({
    width: width,
    height: height,
    frame: false,
    transparent: true,
    alwaysOnTop: true,
    resizable: false,
    movable: false,
    fullscreen: true,
    skipTaskbar: true, // 从任务栏隐藏
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      contextIsolation: true,
      nodeIntegration: false
    }
  });

  // 阻止用户通过快捷键关闭或切换窗口
  overlayWindow.setMenu(null);
  overlayWindow.on('close', (e) => {
    if (overlayWindow) e.preventDefault(); // 除非主动触发恢复,否则禁止关闭
  });

  overlayWindow.loadFile('overlay.html');
}

// IPC 事件监听
ipcMain.on('block-apps', () => {
  createOverlayWindow();
  // 将主窗口置于最上层
  mainWindow.setAlwaysOnTop(true);
});

ipcMain.on('restore-apps', () => {
  if (overlayWindow) {
    overlayWindow.destroy();
    overlayWindow = null;
    mainWindow.setAlwaysOnTop(false);
  }
});

// Electron 生命周期事件
app.whenReady().then(createMainWindow);

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

app.on('activate', () => {
  if (BrowserWindow.getAllWindows().length === 0) createMainWindow();
});

2. 新增预加载脚本 preload.js

const { contextBridge, ipcRenderer } = require('electron');

// 向渲染进程暴露安全的IPC接口
contextBridge.exposeInMainWorld('electronAPI', {
  blockApps: () => ipcRenderer.send('block-apps'),
  restoreApps: () => ipcRenderer.send('restore-apps')
});

3. 修改后的 index.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
  <title>考试模式控制</title>
</head>
<body>
  <h1>考试模式控制</h1>
  <button id="blockButton">启用考试模式</button>

  <script>
    document.getElementById('blockButton').onclick = () => {
      window.electronAPI.blockApps();
    };
  </script>
</body>
</html>

4. 修改后的 overlay.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>考试模式已启用</title>
  <style>
    body {
      background-color: rgba(0, 0, 0, 0.8);
      color: white;
      display: flex;
      align-items: center;
      justify-content: center;
      height: 100vh;
      margin: 0;
      font-size: 2em;
    }
    button {
      padding: 12px 24px;
      font-size: 0.8em;
      cursor: pointer;
      background-color: #4CAF50;
      color: white;
      border: none;
      border-radius: 4px;
    }
  </style>
</head>
<body>
  <div>
    考试模式已启用,无法访问其他应用
    <br><br>
    <button id="restoreButton">退出考试模式</button>
  </div>

  <script>
    document.getElementById('restoreButton').onclick = () => {
      window.electronAPI.restoreApps();
    };
  </script>
</body>
</html>

关键修复点说明

  • 模块引入:补充了Electron核心模块app、BrowserWindow、ipcMain、screen的引入,这是原代码无法运行的首要原因。
  • 逻辑顺序:将变量声明和函数定义放在事件监听之前,避免未定义报错。
  • 安全优化:启用contextIsolation并使用预加载脚本,替代不安全的nodeIntegration: true,符合Electron最新安全规范。
  • 屏幕适配:自动获取主显示器尺寸,替代硬编码的分辨率。
  • 窗口控制:覆盖层窗口添加skipTaskbar: true,并阻止默认关闭行为,增强锁定效果。
  • 主窗口层级:启用考试模式时将主窗口置于最上层,确保用户能操作核心应用。

内容的提问来源于stack exchange,提问作者Sarang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 19:25:55