Skip to content

窗口管理

窗口创建

基本配置

javascript
function createWindow() {
  const win = new BrowserWindow({
    width: 1200,
    height: 800,
    titleBarStyle: getConfigValue('titleBarStyle'),
    trafficLight: false,
    autoHideMenuBar: getConfigValue('autoHideMenuBar'),
    frame: getConfigValue('frame'),
    toolbar: getConfigValue('toolbar'),
    webPreferences: {
      nodeIntegration: false,
      contextIsolation: true,
      sandbox: false,
      webviewTag: true,
      webSecurity: false,
      devTools: true,
      defaultEncoding: 'UTF-8',
      spellcheck: false,
      enableWebSQL: false,
      backgroundThrottling: getConfigValue('enablePerformanceMode'),
      preload: path.join(app.getAppPath(), 'src/preload/preload.js'),
    },
  });

  // 设置图标
  win.setIcon(getAppIcons());

  // 最大化窗口
  win.maximize();

  return win;
}

配置项说明

配置项说明默认值
width / height窗口初始尺寸1200 x 800
titleBarStyle标题栏样式从配置文件读取
autoHideMenuBar自动隐藏菜单栏从配置文件读取
frame是否显示窗口边框从配置文件读取
toolbar是否显示工具栏从配置文件读取

WebPreferences 安全配置

javascript
webPreferences: {
  nodeIntegration: false,      // ❌ 禁用 Node 集成(安全)
  contextIsolation: true,      // ✅ 启用上下文隔离(安全)
  sandbox: false,              // 根据需求配置沙箱
  webviewTag: true,            // ✅ 启用 webview 标签
  webSecurity: false,          // ⚠️ 开发环境可禁用,生产环境建议启用
  devTools: true,              // ✅ 启用开发者工具
  preload: 'path/to/preload.js' // ✅ 指定预加载脚本
}

安全最佳实践:

  • nodeIntegration: false + contextIsolation: true
  • ✅ 使用 preload 脚本暴露安全的 API
  • ❌ 避免在渲染进程直接使用 Node.js 模块

窗口加载

加载模式

支持两种加载模式(详见 加载模式文档):

javascript
async function windowLoadByMode(win, url) {
  const loadMode = getConfigValue('loadMode', LOAD_MODE.REMOTE);

  if (loadMode === LOAD_MODE.REMOTE) {
    // 远程模式:加载远程 URL
    await windowLoadRemoteURL(win, url);
  } else {
    // 本地模式:启动本地 HTTP 服务器
    await windowLoadLocalServer(win);
  }
}

加载远程 URL

javascript
async function windowLoadRemoteURL(win, url) {
  try {
    if (!url) throw new Error('远程URL不能为空');

    logger.info(`开始加载远程URL: ${url}`);
    await win.loadURL(url);
    openDevToolsIfNeeded(win);
    logger.info(`远程URL加载成功: ${url}`);
  } catch (error) {
    logger.error(`加载URL失败: ${url}`, error);
    throw error;
  }
}

加载本地服务器

javascript
async function windowLoadLocalServer(win) {
  try {
    const distPath = path.dirname(LOCAL_WEB_INDEX_FILE);

    // 检查资源是否存在
    if (!fs.existsSync(distPath)) {
      throw new Error(`本地资源目录不存在: ${distPath}`);
    }

    // 启动本地 Express 服务器
    const localServer = LocalServer.getInstance();
    const serverUrl = await localServer.start(distPath);

    logger.info(`开始通过本地服务器加载: ${serverUrl}`);
    await win.loadURL(serverUrl);
    openDevToolsIfNeeded(win);
    logger.info('本地服务器页面加载成功');
  } catch (error) {
    logger.error('启动本地服务器失败:', error);
    throw error;
  }
}

错误处理

当窗口加载失败时,会加载错误兜底页面:

javascript
windowLoadByMode(win, url).catch((error) => {
  logger.error(error.message);
  // LoadErrorHandler 会自动处理并显示错误页面
});

窗口事件处理器

LoadErrorHandler - 加载错误处理

javascript
const errorHandler = new LoadErrorHandler(win);
errorHandler.setOriginalUrl(url);

功能:

  • 监听页面加载失败事件
  • 自动加载错误页面
  • 提供重试功能

OtherActionHandler - 其他动作处理

javascript
new OtherActionHandler(win, FloatingBallService);

功能:

  • 处理窗口最小化、最大化、关闭等操作
  • 与悬浮球服务集成
  • 窗口状态管理

RightMenuHandler - 右键菜单

javascript
if (getConfigValue('showWindowRightMenu')) {
  new RightMenuHandler(win, FloatingBallService);
}

功能:

  • 自定义右键上下文菜单
  • 提供常用操作快捷入口
  • 集成悬浮球功能

ZoomIndicator - 缩放指示器

javascript
if (getConfigValue('showZoomIndicator')) {
  new ZoomIndicator(win);
}

功能:

  • 显示当前缩放级别
  • 缩放操作时的视觉反馈
  • 自动隐藏提示

NativeFocusHandler - 焦点处理

javascript
new NativeFocusHandler(win);

功能:

  • 修复原生 API 焦点问题
  • 处理窗口激活/失活事件
  • 确保输入框焦点正常

窗口操作

基本操作

javascript
// 最大化
win.maximize();

// 最小化
win.minimize();

// 恢复
win.restore();

// 显示/隐藏
win.show();
win.hide();

// 关闭
win.close();

// 全屏
win.setFullScreen(true);

窗口尺寸

javascript
// 设置尺寸
win.setSize(1200, 800);

// 获取尺寸
const [width, height] = win.getSize();

// 设置最小尺寸
win.setMinimumSize(800, 600);

// 设置最大尺寸
win.setMaximumSize(1920, 1080);

窗口位置

javascript
// 设置位置
win.setPosition(100, 100);

// 获取位置
const [x, y] = win.getPosition();

// 居中
win.center();

窗口状态

javascript
// 检查状态
win.isMaximized();
win.isMinimized();
win.isFullScreen();
win.isVisible();
win.isFocused();

// 聚焦
win.focus();

// 模糊
win.blur();

窗口缩放

缩放级别

javascript
// 获取当前缩放级别
const zoomLevel = win.webContents.getZoomLevel();

// 设置缩放级别(-3 到 3)
win.webContents.setZoomLevel(1); // 放大
win.webContents.setZoomLevel(-1); // 缩小
win.webContents.setZoomLevel(0); // 重置

// 缩放因子
const zoomFactor = win.webContents.getZoomFactor();
win.webContents.setZoomFactor(1.2); // 120%

托盘菜单缩放控制

javascript
{
  label: '放大',
  accelerator: 'CmdOrCtrl+Plus',
  click: () => {
    const currentLevel = win.webContents.getZoomLevel();
    win.webContents.setZoomLevel(currentLevel + 1);
  }
},
{
  label: '缩小',
  accelerator: 'CmdOrCtrl+-',
  click: () => {
    const currentLevel = win.webContents.getZoomLevel();
    win.webContents.setZoomLevel(currentLevel - 1);
  }
}

窗口进度条

任务栏进度条

javascript
// 设置进度(0.0 到 1.0)
win.setProgressBar(0.5); // 50%

// 显示不确定进度
win.setProgressBar(2);

// 移除进度条
win.setProgressBar(-1);

// 错误状态(Windows)
win.setProgressBar(0.5, { mode: 'error' });

使用场景:

  • 文件下载
  • 更新安装
  • 数据处理

窗口标题

javascript
// 设置标题
win.setTitle('应用名称 - 加载中...');

// 获取标题
const title = win.getTitle();

// 动态更新
win.webContents.on('page-title-updated', (event, title) => {
  console.log('页面标题:', title);
});

开发者工具

自动打开

javascript
function openDevToolsIfNeeded(win) {
  if (!app.isPackaged) {
    win.webContents.openDevTools();
  }
}

手动控制

javascript
// 打开
win.webContents.openDevTools();

// 关闭
win.webContents.closeDevTools();

// 切换
win.webContents.toggleDevTools();

// 分离模式
win.webContents.openDevTools({ mode: 'detach' });

窗口图标

设置图标

javascript
// Windows/Linux
win.setIcon(getAppIcons());

// macOS(应用图标在打包时配置)
// icon: 'resources/icons/icon.icns'

图标配置

javascript
// packages/main/src/config/app-icon-config.js
function getAppIcons(type = 'default') {
  const platform = process.platform;

  if (platform === 'win32') {
    return type === 'small'
      ? path.join(ICON_DIR, 'icon-16x16.ico')
      : path.join(ICON_DIR, 'icon.ico');
  } else if (platform === 'darwin') {
    return path.join(ICON_DIR, 'icon.icns');
  } else {
    return path.join(ICON_DIR, 'icon.png');
  }
}

窗口生命周期事件

创建和显示

javascript
// 准备显示
win.once('ready-to-show', () => {
  win.show();
});

// 显示完成
win.on('show', () => {
  logger.info('窗口已显示');
});

最小化和恢复

javascript
// 最小化
win.on('minimize', () => {
  logger.info('窗口已最小化');
});

// 恢复
win.on('restore', () => {
  logger.info('窗口已恢复');
});

聚焦和失焦

javascript
// 获得焦点
win.on('focus', () => {
  logger.info('窗口获得焦点');
});

// 失去焦点
win.on('blur', () => {
  logger.info('窗口失去焦点');
});

关闭

javascript
// 关闭前
win.on('close', (event) => {
  // 阻止关闭
  event.preventDefault();

  // 隐藏到托盘而不是退出
  win.hide();
});

// 关闭后
win.on('closed', () => {
  logger.info('窗口已关闭');
  win = null;
});

WebContents 事件

页面导航

javascript
// 即将导航
win.webContents.on('will-navigate', (event, url) => {
  logger.info('即将导航到:', url);

  // 阻止导航
  // event.preventDefault();
});

// 导航完成
win.webContents.on('did-navigate', (event, url) => {
  logger.info('导航完成:', url);
});

页面加载

javascript
// 开始加载
win.webContents.on('did-start-loading', () => {
  logger.info('页面开始加载');
});

// 加载完成
win.webContents.on('did-finish-load', () => {
  logger.info('页面加载完成');
});

// 加载失败
win.webContents.on('did-fail-load', (event, errorCode, errorDescription) => {
  logger.error('页面加载失败:', { errorCode, errorDescription });
});

新窗口

javascript
// 拦截新窗口
win.webContents.setWindowOpenHandler(({ url }) => {
  logger.info('拦截新窗口:', url);

  // 在默认浏览器中打开
  shell.openExternal(url);

  // 阻止在 Electron 中打开
  return { action: 'deny' };
});

崩溃处理

javascript
// 渲染进程崩溃
win.webContents.on('render-process-gone', (event, details) => {
  logger.error('渲染进程崩溃:', details);

  if (details.reason === 'crashed') {
    // 重新加载页面
    win.reload();
  }
});

// 响应超时
win.webContents.on('unresponsive', () => {
  logger.warn('页面无响应');

  dialog
    .showMessageBox(win, {
      type: 'warning',
      message: '页面无响应,是否等待?',
      buttons: ['等待', '重新加载'],
    })
    .then(({ response }) => {
      if (response === 1) win.reload();
    });
});

// 响应恢复
win.webContents.on('responsive', () => {
  logger.info('页面已恢复响应');
});

多窗口管理

获取所有窗口

javascript
const { BrowserWindow } = require('electron');

// 获取所有窗口
const allWindows = BrowserWindow.getAllWindows();

// 获取聚焦的窗口
const focusedWindow = BrowserWindow.getFocusedWindow();

子窗口

javascript
// 创建子窗口
const childWin = new BrowserWindow({
  parent: win, // 设置父窗口
  modal: true, // 模态窗口
  width: 400,
  height: 300,
});

// 子窗口会随父窗口一起最小化/关闭

窗口通信

主进程向渲染进程发送消息

javascript
// 发送消息
win.webContents.send('channel-name', data);

// 广播到所有窗口
BrowserWindow.getAllWindows().forEach((win) => {
  win.webContents.send('channel-name', data);
});

渲染进程向主进程发送消息

详见 IPC通信文档

性能优化

1. 延迟显示

javascript
const win = new BrowserWindow({
  show: false, // 创建时不显示
});

win.once('ready-to-show', () => {
  win.show(); // 准备好后再显示,避免闪烁
});

2. 后台节流

javascript
webPreferences: {
  // 禁用后台节流,保持性能
  backgroundThrottling: false;
}

3. 硬件加速

javascript
// 启用硬件加速(默认开启)
app.disableHardwareAcceleration(); // 禁用(特殊情况)

4. 资源预加载

javascript
// 在 ready-to-show 之前预加载资源
win.webContents.on('did-finish-load', () => {
  // 预加载常用资源
});

最佳实践

1. 安全配置

javascript
✅ 推荐配置
webPreferences: {
  nodeIntegration: false,
  contextIsolation: true,
  sandbox: true,  // 生产环境启用
  preload: 'preload.js'
}

❌ 不推荐
webPreferences: {
  nodeIntegration: true,  // 安全风险
  contextIsolation: false // 安全风险
}

2. 窗口状态持久化

javascript
// 保存窗口状态
app.on('before-quit', () => {
  const [x, y] = win.getPosition();
  const [width, height] = win.getSize();

  store.set('windowBounds', { x, y, width, height });
});

// 恢复窗口状态
const bounds = store.get('windowBounds');
if (bounds) {
  win.setBounds(bounds);
}

3. 优雅的关闭

javascript
win.on('close', (event) => {
  if (!app.isQuitting) {
    event.preventDefault();
    win.hide();
  }
});

app.on('before-quit', () => {
  app.isQuitting = true;
});

4. 资源清理

javascript
win.on('closed', () => {
  // 清理引用,释放内存
  win = null;

  // 清理相关资源
  errorHandler = null;
  updateHandler = null;
});

相关文件

  • packages/main/src/core/window.js - 窗口创建和管理
  • packages/main/src/handlers/load-error-handler.js - 加载错误处理
  • packages/main/src/handlers/other-action-handler.js - 窗口动作处理
  • packages/main/src/handlers/right-menu-handler.js - 右键菜单
  • packages/main/src/handlers/native-focus-handler.js - 焦点处理
  • packages/main/src/indicator/zoom-indicator.js - 缩放指示器

相关文档

基于 MIT 许可发布