Electron 自定義窗口

2023-02-16 17:16 更新

?BrowserWindow? 模塊是您的 Electron 應用程序的基礎。 并且它暴露了許多可以改變您瀏覽器窗口的外觀和行為的API。 在本教程中,我們將介紹在macOS,Windows和Linux上自定義窗口的各種用例。

創(chuàng)建無邊框窗口

無邊框窗口是沒有 chrome 的窗口。 不要與 Google Chrome 瀏覽器混淆,窗口的 chrome 是指窗口的某些部分(例如工具欄、控件等),它們不是網頁的一部分。

要創(chuàng)建無邊框窗口,需在 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 中創(chuàng)建自定義交通燈但仍使用本機 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 是一種網絡標準,它使網絡應用程序能夠在安裝到桌面時自定義其標題欄區(qū)域。 Electron 通過 ?BrowserWindow? 構造函數選項 ?titleBarOverlay? 公開此 API。

只有在 macOS 或 Windows 上應用自定義 ?titlebarStyle? 時,此選項才有效。啟用 ?titleBarOverlay? 后,窗口控件會在其默認位置公開,并且 DOM 元素無法使用該區(qū)域下方的區(qū)域。

?titleBarOverlay? 選項接受兩種不同的值格式。

在任一平臺上指定 ?true? 將導致覆蓋區(qū)域具有默認系統顏色:

// 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 環(huán)境變量從渲染器訪問覆蓋的顏色和尺寸值。

局限性

  • 目前不支持透明顏色??梢栽?nbsp;PR #33567 中找到此功能的進度更新。

創(chuàng)建透明窗口

通過設置 transparent 選項為 true,您可以創(chuàng)建一個完全透明的窗口。

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

局限性

  • 你不能點擊穿透透明區(qū)域。 詳情可見: #1335。
  • 透明窗口不可調整大小。 在某些平臺上,將 resizable 設置為 true 可能會使透明窗口停止工作。
  • CSS blur() 過濾器僅適用于窗口的 Web 內容,因此無法對窗口下方的內容應用模糊效果(即用戶系統上打開的其他應用程序)。

  • 當打開開發(fā)者工具時,窗口將不透明。
  • Windows 上:
    • 當DWM禁用時,透明窗口將失效。
    • 透明窗口不能通過Windows系統菜單或雙擊標題欄實現最大化。 其背后的原因可以在 #28207 這里看到
  • macOS 上:
    • 在 Mac 上, 原生窗口陰影不會顯示在透明窗口中。

創(chuàng)建點擊穿透窗口?

要創(chuàng)建一個點擊穿透窗口,也就是使窗口忽略所有鼠標事件,可以調用 ?win.setIgnoreMouseEvents(ignore)? API:

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

在 macOS Windows 平臺上轉發(fā)鼠標事件

忽略鼠標消息會使網頁內容無視鼠標移動,這意味著鼠標移動事件不會被發(fā)出。 在 Windows 操作系統上,可以使用可選參數將鼠標移動消息轉發(fā)到網頁,從而允許發(fā)出諸如 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 上點擊時穿透,在它外面時恢復正常。

設置自定義可拖動區(qū)域

默認情況下, 無邊框窗口是不可拖拽的。 應用程序需要在 CSS 中指定 -webkit-app-region: drag 來告訴 Electron 哪些區(qū)域是可拖拽的(如操作系統的標準標題欄),在可拖拽區(qū)域內部使用 -webkit-app-region: no-drag 則可以將其中部分區(qū)域排除。 請注意, 當前只支持矩形形狀。

要使整個窗口可拖拽, 您可以添加 -webkit-app-region: drag 作為 body 的樣式:

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

請注意,如果您使整個窗口都可拖拽,則必須將其中的按鈕標記為不可拖拽,否則用戶將無法點擊它們:

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

如果只將自定義標題欄設置為可拖拽,還需要使標題欄中的所有按鈕都不可拖拽。

提示:禁用文本選擇?

創(chuàng)建可拖拽區(qū)域時,拖拽行為可能與文本選擇相沖突。 例如,當您拖動標題欄時,您可能不小心選中其中的文本。 為了避免這種情況,您需要在可拖拽區(qū)域中禁用文本選擇,像這樣:

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

提示:禁用上下文菜單?

在某些平臺上, 可拖拽區(qū)域將被視為non-client frame, 因此當您右鍵單擊它時, 系統菜單將彈出。 要使上下文菜單在所有平臺上都正確運行, 您永遠也不要在可拖拽區(qū)域上使用自定義上下文菜單。


以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號