1、前言
当需要在标题栏添加一些额外的操作时候,比如添加 帮助 菜单,自带的标题栏开发起来比较困难(没了解不知道能不能实现),这时候,自己写一个标题栏就比较方便。
2、实现
首先是禁止掉原先的标题栏,就是创建无边框窗口 (官网描述,点此跳转)
默认情况下, 无边框窗口是不可拖拽的。 应用程序需要在 CSS 中指定 -webkit-app-region: drag 来告诉 Electron 哪些区域是可拖拽的(如操作系统的标准标题栏)设置后点击事件是无效的。
需要在可拖拽区域内部使用 -webkit-app-region: no-drag 则可以将其中部分区域排除。 请注意, 当前只支持矩形形状。(官网描述,点此跳转)
async function createWindow() {
win = new BrowserWindow({
title: 'xxxx工具',
width: 1280,
height: 720,
// 不显示顶部栏
frame: false,
//实际尺寸不包含边框
useContentSize: true,
})
}
然后使用 ipcMain 进行进程通信
监听 最小化、关闭、最大化事件
将代码写在createWindow当中
// 监听放大缩小事件
ipcMain.on('close', () => {
win?.destroy()
})
ipcMain.on('max', () => {
// true表示窗口已最大化.
if (win?.isMaximized()) {
win.restore() // 将窗口恢复为之前的状态
} else {
win?.maximize() // 窗口最大化
}
})
ipcMain.on('min', () => {
win?.minimize()
})
在页面当中可以通过调用这些事件进行窗口的操作,来实现窗口状态的控制
3、优化
但是还可以通过双击标题栏来进行窗口的最大化还原操作
这时候就需要监听到其余最大化窗口和最小化窗口的事件,来改变图标的变化。、
窗口有很多实例事件,可以监听,
这里我们只对最大化和还原进行监听
然后通过webContents
来发送监听到的值到渲染层
// 对双击等其余操作导致的窗口变化监听
// 事件: 最大化
win.on('maximize', () => {
win?.webContents.send('isMaxWindow', win?.isMaximized())
})
// 事件: 还原
win.on('unmaximize', () => {
// 在窗口从最大化状态还原时执行操作
win?.webContents.send('isMaxWindow', win?.isMaximized())
})
页面中使用ipcRenderer
来获取主进程发送过来的值,这样不论是自己点击图标,或者双击、右键改变窗口的状态都可以正确的显示图标。
import {
LineOutlined,
BorderOutlined,
BlockOutlined,
CloseOutlined,
} from '@ant-design/icons'
import { useState, useMemo, FC, useEffect } from 'react'
import styles from './style.module.scss'
type ipcOperateType = 'close' | 'min' | 'max'
type TopPageProps = {
date: string
userCode: string
}
const TopPage: FC<TopPageProps> = () => {
const [isMax, setIsMax] = useState<boolean>(false)
useEffect(() => {
window.ipcRenderer.on('isMaxWindow', (_event, message) => {
setIsMax(message);
});
}, []);
// 窗口事件
const operateWindow = (operate: ipcOperateType) => {
switch (operate) {
case 'close':
window.ipcRenderer.send('close')
break
case 'min':
window.ipcRenderer.send('min')
break
case 'max':
// 监听双击事件以及其余事件导致的窗口全屏还原
window.ipcRenderer.on('isMaxWindow', (_event, message) => {
setIsMax(message)
})
window.ipcRenderer.send('max')
break
}
}
return (
<div className={styles.top_page}>
<div>我是标题xxxxx</div>
<div className={styles.action_box}>
<LineOutlined
onClick={() => {
operateWindow('min')
}}
/>
{!isMax && (
<BorderOutlined
onClick={() => {
operateWindow('max')
}}
/>
)}
{isMax && (
<BlockOutlined
onClick={() => {
operateWindow('max')
}}
/>
)}
<CloseOutlined
onClick={() => {
operateWindow('close')
}}
/>
</div>
</div>
)
}
export default TopPage
此时已经可以实现正常的最小化最大化操作