跳至主要内容

窗口自定义

BrowserWindow 模块是 Electron 应用程序的基础,它公开了许多可以更改浏览器窗口外观和行为的 API。在本教程中,我们将介绍 macOS、Windows 和 Linux 上窗口自定义的各种用例。

创建无边框窗口

无边框窗口是没有边框的窗口。不要与 Google Chrome 浏览器混淆,窗口边框指的是窗口中(例如工具栏、控件)不是网页一部分的部分。

要创建无边框窗口,您需要在 BrowserWindow 构造函数中将 frame 设置为 false

main.js
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ frame: false })

应用自定义标题栏样式 macOS Windows

标题栏样式允许您隐藏大部分 BrowserWindow 的边框,同时保持系统的原生窗口控件完整,并且可以通过 BrowserWindow 构造函数中的 titleBarStyle 选项进行配置。

应用 hidden 标题栏样式会导致标题栏隐藏,并显示全尺寸内容窗口。

main.js
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ titleBarStyle: 'hidden' })

控制交通灯 macOS

在 macOS 上,应用 hidden 标题栏样式仍会在左上角显示标准窗口控件(“交通灯”)。

自定义交通灯的外观 macOS

customButtonsOnHover 标题栏样式会在您将鼠标悬停在它们上面之前隐藏交通灯。如果您想在 HTML 中创建自定义交通灯,但仍使用原生 UI 控制窗口,这将非常有用。

const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ titleBarStyle: 'customButtonsOnHover' })

自定义交通灯位置 macOS

要修改交通灯窗口控件的位置,有两个可用的配置选项。

应用 hiddenInset 标题栏样式会将交通灯的垂直内边距偏移固定数量。

main.js
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ titleBarStyle: 'hiddenInset' })

如果您需要更精细地控制交通灯的位置,您可以将一组坐标传递给 BrowserWindow 构造函数中的 trafficLightPosition 选项。

main.js
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({
titleBarStyle: 'hidden',
trafficLightPosition: { x: 10, y: 10 }
})

以编程方式显示和隐藏交通灯 macOS

您还可以从主进程以编程方式显示和隐藏交通灯。win.setWindowButtonVisibility 会根据其布尔参数的值强制显示或隐藏交通灯。

main.js
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
// hides the traffic lights
win.setWindowButtonVisibility(false)

注意:鉴于可用的 API 数量众多,实现此目标的方法有很多种。例如,将 frame: falsewin.setWindowButtonVisibility(true) 结合使用将产生与设置 titleBarStyle: 'hidden' 相同的布局结果。

窗口控件叠加层

窗口控件叠加层 API 是一种 Web 标准,它使 Web 应用能够在安装到桌面上时自定义其标题栏区域。Electron 通过 BrowserWindow 构造函数选项 titleBarOverlay 公开了此 API。

此选项仅在应用自定义 titlebarStyle 时有效。启用 titleBarOverlay 时,窗口控件将以其默认位置显示,并且 DOM 元素不能使用此区域下方的区域。

titleBarOverlay 选项接受两种不同的值格式。

在任何平台上指定 true 都会导致一个具有默认系统颜色的叠加区域

main.js
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({
titleBarStyle: 'hidden',
titleBarOverlay: true
})

在任何平台上,titleBarOverlay 也可以是一个对象。叠加层的高度可以通过 height 属性指定。在 Windows 和 Linux 上,可以使用 color 属性指定叠加层的颜色。在 Windows 和 Linux 上,可以使用 colorsymbolColor 属性分别指定叠加层及其符号的颜色。支持 rgba()hsla()#RRGGBBAA 颜色格式以应用透明度。

如果未指定颜色选项,则颜色将默认为其窗口控制按钮的系统颜色。类似地,如果未指定高度选项,则它将默认为默认高度

main.js
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({
titleBarStyle: 'hidden',
titleBarOverlay: {
color: '#2f3241',
symbolColor: '#74b1be',
height: 60
}
})

注意:一旦从主进程启用标题栏叠加层,您就可以使用一组只读JavaScript APICSS 环境变量从渲染器访问叠加层的颜色和尺寸值。

创建透明窗口

通过将 transparent 选项设置为 true,您可以创建一个完全透明的窗口。

main.js
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ transparent: true })

限制

  • 您无法点击透明区域。有关详细信息,请参阅#1335
  • 透明窗口不可调整大小。将 resizable 设置为 true 可能会导致透明窗口在某些平台上停止工作。
  • CSS blur() 滤镜仅应用于窗口的 Web 内容,因此无法将模糊效果应用于窗口下方的内容(即用户系统上打开的其他应用程序)。
  • 当打开 DevTools 时,窗口将不透明。
  • Windows
    • 禁用 DWM 时,透明窗口将无法工作。
    • 无法使用 Windows 系统菜单或双击标题栏来最大化透明窗口。其背后的原因可以在 PR #28207 上看到。
  • macOS
    • 透明窗口上不会显示原生窗口阴影。

创建点击穿透窗口

要创建点击穿透窗口,即使窗口忽略所有鼠标事件,您可以调用 win.setIgnoreMouseEvents(ignore) API

main.js
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
win.setIgnoreMouseEvents(true)

转发鼠标事件 macOS Windows

忽略鼠标消息会使 Web 内容忽略鼠标移动,这意味着不会发出鼠标移动事件。在 Windows 和 macOS 上,可以使用可选参数将鼠标移动消息转发到网页,从而允许发出诸如 mouseleave 之类的事件

main.js
const { BrowserWindow, ipcMain } = require('electron')
const path = require('node:path')

const win = new BrowserWindow({
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})

ipcMain.on('set-ignore-mouse-events', (event, ignore, options) => {
const win = BrowserWindow.fromWebContents(event.sender)
win.setIgnoreMouseEvents(ignore, options)
})
preload.js
window.addEventListener('DOMContentLoaded', () => {
const el = document.getElementById('clickThroughElement')
el.addEventListener('mouseenter', () => {
ipcRenderer.send('set-ignore-mouse-events', true, { forward: true })
})
el.addEventListener('mouseleave', () => {
ipcRenderer.send('set-ignore-mouse-events', false)
})
})

这使得网页在 #clickThroughElement 元素上时点击穿透,并在其外部恢复正常。

设置自定义可拖动区域

默认情况下,无边框窗口不可拖动。应用需要在 CSS 中指定 -webkit-app-region: drag 来告诉 Electron 哪些区域是可拖动的(如操作系统的标准标题栏),并且应用也可以使用 -webkit-app-region: no-drag 从可拖动区域排除不可拖动的区域。请注意,目前仅支持矩形形状。

要使整个窗口可拖动,您可以将 -webkit-app-region: drag 添加为 body 的样式

styles.css
body {
-webkit-app-region: drag;
}

并且请注意,如果您已使整个窗口可拖动,则还必须将按钮标记为不可拖动,否则用户将无法点击它们

styles.css
button {
-webkit-app-region: no-drag;
}

如果您仅将自定义标题栏设置为可拖动,则还需要使标题栏中的所有按钮都不可拖动。

提示:禁用文本选择

创建可拖动区域时,拖动行为可能会与文本选择冲突。例如,当您拖动标题栏时,您可能会意外选择其文本内容。为防止这种情况,您需要在可拖动区域内禁用文本选择,如下所示

.titlebar {
-webkit-user-select: none;
-webkit-app-region: drag;
}

提示:禁用上下文菜单

在某些平台上,可拖动区域将被视为非客户端框架,因此当您在其上单击鼠标右键时,系统菜单将弹出。为了使上下文菜单在所有平台上都正常运行,您不应在可拖动区域上使用自定义上下文菜单。