文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
自定义窗口标题栏
在 src/renderer/components 下新建 BarTop.vue,这是窗口标题栏组件:
<template>
<div class="topBar">
<div class="winTitle">{{ title }}}</div>
<div class="winTool">
<div @click="minimizeMainWindow">
<i class="icon icon-minimize"/>
</div>
<div v-if="isMaximized" @click="unmaximizeMainWindow">
<i class="icon icon-restore"/>
</div>
<div v-else @click="maxmizeMainWin">
<i class="icon icon-maximize"/>
</div>
<div @click="closeWindow">
<i class="icon icon-close"/>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
</script>
<style lang="scss" scoped>
.topBar {
display: flex;
height: 25px;
line-height: 25px;
-webkit-app-region: drag; /* 可拖拽区域 */
width: 100%;
}
.winTitle {
flex: 1;
padding-left: 12px;
font-size: 14px;
color: #888;
}
.winTool {
height: 100%;
display: flex;
-webkit-app-region: no-drag; /* 可拖拽区域内的不可拖拽区域 */
}
.winTool div {
height: 100%;
width: 34px;
text-align: center;
color: #999;
cursor: pointer;
line-height: 25px;
}
.winTool .icon {
font-size: 10px;
color: #666666;
font-weight: bold;
}
.winTool div:hover {
background: #efefef;
}
.winTool div:last-child:hover {
background: #ff7875;
}
.winTool div:last-child:hover i {
color: #fff !important;
}
</style>
- 要自定义一个窗口的标题栏必须把窗口默认的标题栏取消掉才行。只需要在初始化 mainWindow 对象时(主进程里的逻辑),把窗口配置对象的 frame 属性设置为 false 就可以使这个窗口成为无边框窗口了。
- 窗口标题是通过 props 数据传递给标题栏组件的,也就是说标题栏的标题是由其父组件来确定的。
- 标题栏中可拖拽区域是通过样式 -webkit-app-region: drag 定义的,鼠标在这个样式定义的组件上拖拽可以移动窗口,双击可以放大或者还原窗口,如果这个组件内有子组件不希望拥有该能力,可以通过 -webkit-app-region: no-drag; 来取消此能力。
- 最大化、最小化、还原、关闭窗口等按钮的点击事件,都是通过 ipcRenderer.invoke 方法来调用主进程 CommonWindowEvent 类提供的消息管道来实现对应的功能的。
- 由于窗口最大化(或还原)不一定是通过点击最大化按钮(或还原按钮)触发的,有可能是通过双击标题栏可拖拽区域触发的,所以这里只能通过 ipcRenderer.on 来监听窗口的最大化或还原事件,以此来改变对应的最大化或还原按钮的显隐状态。不能在按钮点击事件中来完成这项工作。windowMaximized 消息和 windowUnmaximized 消息也是由主进程的 CommonWindowEvent 类发来的。
- 由于多个二级路由页面会引用 BarTop.vue,为了避免在切换路由的时候,反复通过 ipcRenderer.on 注册消息监听器,所以在组件的 onUnmounted 事件内注销了消息监听器,避免事件泄漏。
src/main/CommonWindowEvent.ts 的代码如下:
import { BrowserWindow, ipcMain, app } from 'electron';
// 主进程公共消息处理逻辑
export class CommonWindowEvent {
private static getWin(event: any) {
return BrowserWindow.fromWebContents(event.sender);
}
public static listen() {
ipcMain.handle('minimizeWindow', e => {
this.getWin(e)?.minimize();
});
ipcMain.handle('maxmizeWindow', e => {
this.getWin(e)?.maximize();
});
ipcMain.handle('unmaximizeWindow', e => {
this.getWin(e)?.unmaximize();
});
ipcMain.handle('hideWindow', e => {
this.getWin(e)?.hide();
});
ipcMain.handle('showWindow', e => {
this.getWin(e)?.show();
});
ipcMain.handle('closeWindow', e => {
this.getWin(e)?.close();
});
ipcMain.handle('resizable', e => this.getWin(e)?.isResizable());
ipcMain.handle('getPath', (e, name) => app.getPath(name));
}
// 主进程公共事件处理逻辑
public static regWinEvent(win: BrowserWindow) {
win.on('maximize', () => {
win.webContents.send('windowMaximized');
});
win.on('unmaximize', () => {
win.webContents.send('windowUnmaximized');
})
}
}
- 在 listen 方法内部注册了一系列消息管道,方便渲染进程控制主进程的一些行为,标题栏组件的窗口的最大化、最小化、还原等功能都是在这里实现的。在 app ready 之后调用 CommonWindowEvent.listen(); 这个方法即可注册这些消息管道。
- regWinEvent 方法负责为窗口对象注册事件,当窗口最大化或还原后,这些事件的处理函数负责把消息发送给渲染进程。标题栏的对应按钮的图标也会发生相应的变化,同样也是在 app ready 之后调用 CommonWindowEvent.regWinEvent(mainWindow); 这个方法即可。
在 src/main/mainEntry.ts 下添加如下代码:
import {app, BrowserWindow} from 'electron';
import {CustomScheme} from "./customScheme";
import { CommonWindowEvent } from "./CommonWindowEvent";
process.env.ELECTRON_DISABLE_SECURITY_WARNINGS = 'true';
let mainWindow: BrowserWindow;
// 调用 CommonWindowEvent.regWinEvent(win);
app.on("browser-window-created", (e, win) => {
CommonWindowEvent.regWinEvent(win);
});
app.whenReady().then(() => {
let config = {
webPreferences: {
nodeIntegration: true,
webSecurity: false,
allowRunningInsecureContent: true,
contextIsolation: false,
webviewTag: true,
spellcheck: false,
disableHtmlFullscreenWindowResize: true,
},
};
mainWindow = new BrowserWindow(config);
mainWindow.webContents.openDevTools({mode: 'undocked'});
if (process.argv[2]) {
mainWindow.loadURL(process.argv[2]);
} else {
CustomScheme.registerScheme();
mainWindow.loadURL('app"//index.html');
}
// 调用 CommonWindowEvent.listen();
CommonWindowEvent.listen();
});
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论