Electron 自定义窗口

2023-02-16 17:16 更新

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

创建无边框窗口

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

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

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

应用自定义标题栏样式

标题栏样式允许隐藏浏览器窗口的大部分色彩,同时保持系统原生窗口控件完整无损,并可以在 BrowserWindow 的构造器中使用 titleBarStyle 选项来配置。

应用 hidden 标题栏样式的结果是隐藏标题栏和全尺寸内容窗口。

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

控制红绿灯

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

自定义交通灯的外观

customButtonsOnHover​ 标题栏样式将隐藏交通灯,直到您将鼠标悬停在它们上方。如果您想在 HTML 中创建自定义交通灯但仍使用本机 UI 来控制窗口,这将很有用。

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

自定义红绿灯位置

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

应用 ​hiddenInset​ 标题栏样式会将交通灯的垂直插入移动固定量。

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

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

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

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

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

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

注意:考虑到可用 API 的数量,有很多方法可以实现这一点。例如,将 ​frame: false​ 与 ​win.setWindowButtonVisibility(true)​ 组合将产生与设置 ​titleBarStyle: 'hidden'​ 相同的布局结果。

窗口控件覆盖

Window Controls Overlay API 是一种网络标准,它使网络应用程序能够在安装到桌面时自定义其标题栏区域。 Electron 通过 ​BrowserWindow​ 构造函数选项 ​titleBarOverlay​ 公开此 API。

只有在 macOS 或 Windows 上应用自定义 ​titlebarStyle​ 时,此选项才有效。启用 ​titleBarOverlay​ 后,窗口控件会在其默认位置公开,并且 DOM 元素无法使用该区域下方的区域。

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

在任一平台上指定 ​true​ 将导致覆盖区域具有默认系统颜色:

// on macOS or Windows
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({
  titleBarStyle: 'hidden',
  titleBarOverlay: true
})

在任一平台上,​titleBarOverlay​ 也可以是一个对象。在 macOS 和 Windows 上,可以使用 ​height​ 属性指定叠加层的高度。在 Windows 上,可以分别使用 ​color​ 和 ​symbolColor​ 属性指定叠加层及其符号的颜色。

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

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

注意:从主进程启用标题栏覆盖后,您可以使用一组只读 JavaScript API 和 CSS 环境变量从渲染器访问覆盖的颜色和尺寸值。

局限性

  • 目前不支持透明颜色。可以在 PR #33567 中找到此功能的进度更新。

创建透明窗口

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

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

局限性

  • 你不能点击穿透透明区域。 详情可见: #1335
  • 透明窗口不可调整大小。 在某些平台上,将 resizable 设置为 true 可能会使透明窗口停止工作。
  • CSS blur() 过滤器仅适用于窗口的 Web 内容,因此无法对窗口下方的内容应用模糊效果(即用户系统上打开的其他应用程序)。

  • 当打开开发者工具时,窗口将不透明。
  • Windows 上:
    • 当DWM禁用时,透明窗口将失效。
    • 透明窗口不能通过Windows系统菜单或双击标题栏实现最大化。 其背后的原因可以在 #28207 这里看到
  • macOS 上:
    • 在 Mac 上, 原生窗口阴影不会显示在透明窗口中。

创建点击穿透窗口

要创建一个点击穿透窗口,也就是使窗口忽略所有鼠标事件,可以调用 ​win.setIgnoreMouseEvents(ignore)​ API:

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

在 macOS Windows 平台上转发鼠标事件

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

const { BrowserWindow, ipcMain } = require('electron')
const path = require('path')

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

ipcMain.on('set-ignore-mouse-events', (event, ...args) => {
  const win = BrowserWindow.fromWebContents(event.sender)
  win.setIgnoreMouseEvents(...args)
})
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 的样式:

body {
  -webkit-app-region: drag;
}

请注意,如果您使整个窗口都可拖拽,则必须将其中的按钮标记为不可拖拽,否则用户将无法点击它们:

button {
  -webkit-app-region: no-drag;
}

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

提示:禁用文本选择

创建可拖拽区域时,拖拽行为可能与文本选择相冲突。 例如,当您拖动标题栏时,您可能不小心选中其中的文本。 为了避免这种情况,您需要在可拖拽区域中禁用文本选择,像这样:

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

提示:禁用上下文菜单

在某些平台上, 可拖拽区域将被视为non-client frame, 因此当您右键单击它时, 系统菜单将弹出。 要使上下文菜单在所有平台上都正确运行, 您永远也不要在可拖拽区域上使用自定义上下文菜单。


以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号