Appearance
窗口定义
窗口管理
每一个窗口可以简单理解成一个chrome浏览器标签,需要在在electron主文件 electron/main/index.ts 中定义。
- 窗口可以定义尺寸
- 窗口可以加载本地文件或一个链接
下面我们创建窗口并加载斑马兽网站链接
function createWindow() {
...
const bmWin = new BrowserWindow({
title: '斑马兽',
width: 390,
height: 844,
})
bmWin.loadURL('https://www.banmashou.com')
...
}
下面在项目根据目录创建文件 bm.html ,并使用窗口加载该文件
const bmWin = new BrowserWindow({
title: '斑马兽',
icon: path.resolve(__dirname, 'favicon.ico')
})
bmWin.loadFile(path.join(__dirname, '../../bm.html'))
bmWin.webContents.openDevTools()
常用方法
下面介绍窗口实例常用的方法
方法 | 说明 |
---|---|
win.loadFile() | 加载文件 |
win.loadURL() | 加载链接 |
win.webContents.openDevTools() | 打开开发者工具 |
win.setContentBounds() | 控制窗口尺寸与位置 |
win.center() | 将窗口移动到屏幕中心 |
常用属性
下面介绍常用的窗口属性
属性 | 说明 |
---|---|
title | 标题,也可以修改html模板的title标签,模板的title标签优先级高 |
icon | window系统窗口图标 |
frame | 是否显示边框 |
transparent | 窗口是否透明 |
x | x坐标 |
y | y坐标 |
width | 宽度 |
height | 高度 |
movable | 是否可以移动窗口 |
minHeight | 最小高度,不能缩放小于此高度 |
minWidth | 最大高度,不能缩放小于此高度 |
resizable | 是否允许缩放窗口 |
alwaysOnTop | 窗口是否置顶 |
autoHideMenuBar | 是否自动隐藏窗口菜单栏。 一旦设置,菜单栏将只在用户单击 Alt 键时显示 |
fullscreen | 是否全屏幕 |
属性举例
下面演示一些窗口使用的案例
ready-to-show
如果应用过于复杂,在加载本地资源时出现白屏,这时可以监测窗口的 ready-to-show 事件。
- 设置show属性为false,让窗口不显示
- 可以通过设置backgroundColor属性指定应用背景颜色,使界面不显示突兀
- ready-to-show事件检测,当渲染进程绘制完成时,显示窗口
...
const createWindow = () => {
const win = new BrowserWindow({
width: 600,
height: 500,
show: false,
backgroundColor: 'red',
})
win.loadFile(path.resolve(__dirname, 'index.html'))
win.once('ready-to-show', () => {
win.show()
})
}
...
窗口定位
下面将窗口定位到屏幕右侧顶部,需要使用到 electron 库的 screen对象。
const { app, BrowserWindow, shell, ipcMain, screen } = require('electron')
function createWindow() {
win = new BrowserWindow({
title: 'Main window',
x: screen.getPrimaryDisplay().workAreaSize.width - 414,
y: 0,
width: 414,
height: 736
})
...
}
窗口居中
我们有多种方式实现窗口居中,首先使用 win.center() 方法操作
...
mainWindow.webContents.openDevTools()
mainWindow.loadFile(path.resolve(__dirname, 'index.html'))
mainWindow.center()
...
也可以通过screen模块获取屏幕尺寸,经过计算后设置窗口居中
- screen.getPrimaryDisplay().workAreaSize 获取窗口尺寸
- mainWindow.setContentBounds() 设置窗口尺寸与坐标,每二个参数用于定义是否使用过渡动画
...
const mainWindow = new BrowserWindow({
width: 300,
height: 300,
x: 1500,
y: 100,
alwaysOnTop: true,
webPreferences: {
preload: path.resolve(__dirname, 'preload.js'),
},
})
mainWindow.webContents.openDevTools()
mainWindow.loadFile(path.resolve(__dirname, 'index.html'))
setTimeout(() => {
mainWindow.setContentBounds(
{
width: 300,
height: 300,
x: screen.getPrimaryDisplay().workAreaSize.width / 2 - 150,
y: 100,
},
true,
)
}, 1000)
...
改变位置
使用 setContentBounds 可以改变窗口的尺寸与位置,第二个参数指定是否使用动画
...
win.loadFile(path.resolve(__dirname, 'index.html'))
setTimeout(() => {
win.setContentBounds({ height: 100, width: 100, x: 0, y: 0 }, true)
}, 2000)
...
动态修改窗口
下面通过动态修改窗口大小的案例来把窗口属性的使用解释一下。

main.js
const { app, ipcMain, BrowserWindow, screen } = require('electron')
const { createWindow } = require('./window')
app.whenReady().then(() => {
createWindow()
})
ipcMain.on('setPostion', (event, options) => {
//获取窗口
const win = BrowserWindow.fromWebContents(event.sender)
//根据屏幕尺寸获取窗口的x坐标,使其居中显示
const primaryDisplay = screen.getPrimaryDisplay()
const { width, height } = primaryDisplay.workAreaSize
const x = width / 2 - options.width / 2
//设置窗口坐标
win.setContentBounds({ ...options, x, y: 100 }, true)
})
window.js
该文件用于定义窗口
const { BrowserWindow } = require('electron')
const path = require('path')
const createWindow = () => {
const mainWindow = new BrowserWindow({
width: 300,
height: 300,
x: 1500,
y: 100,
alwaysOnTop: true,
webPreferences: {
preload: path.resolve(__dirname, 'preload.js'),
},
})
mainWindow.webContents.openDevTools()
mainWindow.loadFile(path.resolve(__dirname, 'index.html'))
return mainWindow
}
module.exports = {
createWindow,
}
preload.js
预加载脚本用于IPC通信
const { ipcRenderer, contextBridge } = require('electron')
contextBridge.exposeInMainWorld('api', {
changeWindowPos: (options) => {
ipcRenderer.send('setPostion', options)
},
})
renderer.js
渲染进程用于接收按钮事件,然后通过preload.js调用main.js的事件,改变窗口大小。
window.addEventListener('DOMContentLoaded', () => {
const btn = document.querySelector('button')
btn.addEventListener('click', () => {
window.api.changeWindowPos({
width: Number(document.querySelector('[name="width"]').value),
height: Number(document.querySelector('[name="height"]').value),
})
})
})
index.html
模板文件定义改变窗口的表单
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'" />
<title>banmashou</title>
</head>
<body>
宽度:<input type="text" name="width" value="500" /> <br />
调试:<input type="text" name="height" value="500" />
<button>改变位置</button>
<script src="renderer.js"></script>
</body>
</html>
BrowserView
BrowserView
被用来让 BrowserWindow
嵌入更多的 web 内容。 它就像一个子窗口,除了它的位置是相对于父窗口。
下面演示使用 BrowserView 在主窗口中嵌入网页。
const win = new BrowserWindow({
width: 1024,
height: 500,
frame: false,
webPreferences: {
preload: path.resolve(__dirname, 'preload.js')
},
})
win.webContents.openDevTools()
win.loadFile(path.resolve(__dirname, 'index.html'))
const view = new BrowserView()
win.setBrowserView(view)
view.setBounds({
x: 0,
y: 0,
width: win.getBounds().width,
height: 300,
})
view.webContents.loadURL('https://www.banmashou.com')
Shell
electron的 shell 模块是使用操作系统的默认应用程序打开文件或 url。
可以在 Main, Renderer (只能在非沙盒下使用) 进程中使用
案例分析
下面演示使用 shell 模块,用操作系统的默认浏览器打开网页链接。
index.html 模板文件
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'" />
<meta http-equiv="X-Content-Security-Policy" content="default-src 'self'; script-src 'self'" />
<title>banmashou</title>
</head>
<body>
<a href="https://www.banmashou.com" target="__blank">斑马兽</a>
<script src="renderer.js"></script>
</body>
</html>
main.js 主进程脚本
const { app, shell } = require('electron')
const { BrowserWindow } = require('electron/main')
const path = require('path')
const createWindow = () => {
const win = new BrowserWindow({
width: 500,
height: 500,
})
win.loadFile(path.resolve(__dirname, 'index.html'))
//捕获a标签的打开事件,使用系统浏览器打开,并阻止新窗口打开
win.webContents.setWindowOpenHandler((details) => {
shell.openExternal(details.url)
//action:deny 拒绝electron新建窗口打开
//action:allow 允许electron新建窗口打开
return { action: 'deny' }
})
}
app.whenReady().then(() => {
createWindow()
})