electron-vite【实战】自定义标题栏【组件封装】(含异形标题栏,指定区域拖拽,窗口置顶,窗口最小化,窗口最大化,取消最大化,隐藏窗口到托盘等)
效果预览
技术要点
透明背景
src/main/index.ts 的 new BrowserWindow 中添加
transparent: true, // 设置窗口背景透明frame: false, // 隐藏窗口边框
仅图标和标题部分可拖拽
仅图标和标题部分添加样式 drag
.drag {-webkit-app-region: drag;
}
图标与标题栏的融合
- 标题栏的背景色采用图标的背景色
bg-[#0baaf5]
- 标题栏添加顶部的外边距,值为图标的半径
mt-30px
图标的样式如下:
<img :src="icon" alt="logo" class="fixed h-60px top-[0px] drag" />
窗口置顶
<Iconv-if="ifTop"icon="stash:pin-thumbtack-solid":class="iconClassString"@click="cancle_top"/><Icon v-else icon="stash:pin-thumbtack" :class="iconClassString" @click="top" />
const ifTop = ref(false)// 窗口置顶
function top() {window.electron.ipcRenderer.send('top')ifTop.value = true
}function cancle_top() {window.electron.ipcRenderer.send('cancle_top')ifTop.value = false
}
src/main/index.ts 中
ipcMain.on('top', () => {mainWindow.setAlwaysOnTop(true)})ipcMain.on('cancle_top', () => {mainWindow.setAlwaysOnTop(false)})
窗口最小化
<Icon icon="qlementine-icons:windows-minimize-16" :class="iconClassString" @click="min" />
function min() {window.electron.ipcRenderer.send('min')
}
src/main/index.ts 中
ipcMain.on('min', () => {mainWindow.minimize()})
窗口最大化 / 取消最大化
<Iconv-if="ifMax"icon="qlementine-icons:windows-unmaximize-16":class="iconClassString"@click="cancel_max"/><Iconv-elseicon="qlementine-icons:windows-maximize-16":class="iconClassString"@click="max"/>
const ifMax = ref(false)function max() {window.electron.ipcRenderer.send('max')
}function cancel_max() {window.electron.ipcRenderer.send('cancel_max')
}window.electron.ipcRenderer.on('unmaximize', () => {ifMax.value = false
})window.electron.ipcRenderer.on('maximize', () => {ifMax.value = true
})
src/main/index.ts 中
ipcMain.on('max', () => {mainWindow.maximize()})ipcMain.on('cancel_max', () => {mainWindow.unmaximize()})
因将窗口拖拽到屏幕边缘时,会自动触发最大化,调整窗口大小会退出最大化,则需监听窗口最大化和退出最大化事件,由主进程通知渲染进程状态,以便切换图标。[ 不适应于本范例,因本范例隐藏了 frame ]
// 窗口变为最大化状态mainWindow.on('maximize', () => {mainWindow.webContents.send('maximize')})// 窗口从最大化状态退出mainWindow.on('unmaximize', () => {mainWindow.webContents.send('unmaximize')})
隐藏窗口到托盘
<Icon icon="si:close-fill" :class="iconClassString" @click="hide" />
function hide() {window.electron.ipcRenderer.send('hide')
}
src/main/index.ts 中
ipcMain.on('hide', () => {// 使窗口不显示在任务栏中mainWindow.setSkipTaskbar(true)mainWindow.hide()})
代码实现
src/renderer/src/components/TitleBar.vue
<script setup lang="ts">
import icon from '../../../../resources/icon.png'
const props = defineProps({title: {type: String}
})function hide() {window.electron.ipcRenderer.send('hide')
}const ifTop = ref(false)// 窗口置顶
function top() {window.electron.ipcRenderer.send('top')ifTop.value = true
}function cancle_top() {window.electron.ipcRenderer.send('cancle_top')ifTop.value = false
}function min() {window.electron.ipcRenderer.send('min')
}const ifMax = ref(false)function max() {window.electron.ipcRenderer.send('max')
}function cancel_max() {window.electron.ipcRenderer.send('cancel_max')
}window.electron.ipcRenderer.on('unmaximize', () => {ifMax.value = false
})window.electron.ipcRenderer.on('maximize', () => {ifMax.value = true
})const iconClassString = 'cursor-pointer hover:bg-blue-500 block h-full px-2'
</script><template><img :src="icon" alt="logo" class="fixed h-60px top-[0px] drag" /><div class="flex items-center bg-[#0baaf5] text-white h-30px mt-30px"><div class="drag flex-1 pl-70px font-bold text-white">{{ props.title }}</div><div class="flex h-full"><Iconv-if="ifTop"icon="stash:pin-thumbtack-solid":class="iconClassString"@click="cancle_top"/><Icon v-else icon="stash:pin-thumbtack" :class="iconClassString" @click="top" /><Icon icon="qlementine-icons:windows-minimize-16" :class="iconClassString" @click="min" /><Iconv-if="ifMax"icon="qlementine-icons:windows-unmaximize-16":class="iconClassString"@click="cancel_max"/><Iconv-elseicon="qlementine-icons:windows-maximize-16":class="iconClassString"@click="max"/><Icon icon="si:close-fill" :class="iconClassString" @click="hide" /></div></div>
</template>
页面使用
<TitleBar title="邀请函" />
src/main/index.ts
import { app, shell, BrowserWindow, ipcMain, Tray, Menu } from 'electron'
import { join } from 'path'
import { electronApp, optimizer, is } from '@electron-toolkit/utils'
import icon from '../../resources/icon.png?asset'function createWindow(): void {const mainWindow = new BrowserWindow({// 自定义图标icon: icon,// 自定义窗口宽度width: 360,// 自定义窗口高度height: 430,//默认隐藏窗口show: false,// 隐藏窗口标题栏titleBarStyle: 'hidden',// 隐藏默认菜单autoHideMenuBar: true,// 不可改变窗口大小resizable: false,// 不可改变窗口大小maximizable: false,transparent: true, // 设置窗口背景透明frame: false, // 隐藏窗口边框webPreferences: {preload: join(__dirname, '../preload/index.js'),sandbox: false}})// 托盘const tray = new Tray(icon)const contextMenu = [{label: '退出',click: function () {app.exit()}}]const menu = Menu.buildFromTemplate(contextMenu)tray.setToolTip('EC编程俱乐部')tray.setContextMenu(menu)tray.on('click', () => {// 使窗口显示在任务栏中mainWindow.setSkipTaskbar(false)mainWindow.show()})// IPC通信ipcMain.on('showPage_home', () => {// 窗口可调整大小mainWindow.setResizable(true)mainWindow.setSize(800, 720)// 窗口居中mainWindow.center()// 窗口可最大化mainWindow.setMaximizable(true)})ipcMain.on('top', () => {mainWindow.setAlwaysOnTop(true)})ipcMain.on('cancle_top', () => {mainWindow.setAlwaysOnTop(false)})ipcMain.on('hide', () => {// 使窗口不显示在任务栏中mainWindow.setSkipTaskbar(true)mainWindow.hide()})ipcMain.on('min', () => {mainWindow.minimize()})ipcMain.on('max', () => {mainWindow.maximize()})ipcMain.on('cancel_max', () => {mainWindow.unmaximize()})mainWindow.on('ready-to-show', () => {// 自定义标题mainWindow.setTitle('EC编程俱乐部')mainWindow.show()})// 窗口变为最大化状态mainWindow.on('maximize', () => {mainWindow.webContents.send('maximize')})// 窗口从最大化状态退出mainWindow.on('unmaximize', () => {mainWindow.webContents.send('unmaximize')})mainWindow.webContents.setWindowOpenHandler((details) => {shell.openExternal(details.url)return { action: 'deny' }})if (is.dev && process.env['ELECTRON_RENDERER_URL']) {mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL'])} else {mainWindow.loadFile(join(__dirname, '../renderer/index.html'))}
}app.whenReady().then(() => {// Set app user model id for windowselectronApp.setAppUserModelId('com.electron')app.on('browser-window-created', (_, window) => {optimizer.watchWindowShortcuts(window)})createWindow()app.on('activate', function () {if (BrowserWindow.getAllWindows().length === 0) createWindow()})
})ipcMain.on('quit', () => {app.quit()
})app.on('window-all-closed', () => {if (process.platform !== 'darwin') {app.quit()}
})
相关文章:

electron-vite【实战】自定义标题栏【组件封装】(含异形标题栏,指定区域拖拽,窗口置顶,窗口最小化,窗口最大化,取消最大化,隐藏窗口到托盘等)
效果预览 技术要点 透明背景 src/main/index.ts 的 new BrowserWindow 中添加 transparent: true, // 设置窗口背景透明frame: false, // 隐藏窗口边框仅图标和标题部分可拖拽 仅图标和标题部分添加样式 drag .drag {-webkit-app-region: drag; }图标与标题栏的融合 标题栏的…...

vue2 项目webpack 4升5
项目背景 公司项目需要将进行微前端改造.主应用和子应用会需要共享依赖,考虑使用模块联邦进行依赖共享. 由于模块联邦要升级到webpack 5才能用,所以老项目要从webpack 4升级到webpack 5 实现思路 原来的项目用的是vue-cli 3,查了一下可以vue-cli 5用的就是webpack 5,所以可以…...

前端开发性能监控中的数据采集与性能调优方法
🌟 前端开发性能监控中的数据采集与性能调优方法 📖 前言 在现代 Web 应用中,性能是用户体验的关键因素之一。性能问题不仅会影响用户满意度,还可能导致业务损失。如何高效地监控前端性能并进行性能调优,成为每个开发…...

S32K324 Stack异常分析及解决方案
文章目录 前言正向排查尝试反向排查问题原因分析问题解决处理总结前言 在项目开发过程中,在一次软件变更时,调整了task优先级之后导致应用层软件中的float数据经常性的变为NAN,导致应用层功能失效。本文记录下这个bug的分析及解决过程。 正向排查尝试 由于问题复现的概率…...

[创业之路-202]:任正非管理华为的思想与毛泽东管理党、军队、国家的思想的相似性与差异性
目录 一、相似性 1、指导思想 2、管理策略 3、危机意识与自我否定 4、理想主义与奋斗精神 二、差异性 1、哲学基础与思想倾向 2、管理方法与策略 3、组织文化与价值观 一、相似性 任正非管理华为的思想与毛泽东管理党、军队、国家的思想在多个方面存在相似性。 以下…...

SAP PP ECN CSAP_MAT_BOM_MAINTAIN
刚开始的时候ECN总是加不上, 参考kimi给出的案例 点击链接查看和 Kimi 智能助手的对话 https://kimi.moonshot.cn/share/cth1ipmqvl7f04qkggdg 效果 加上了 FUNCTION ZPBOM_PLM2SAP. *"------------------------------------------------------------------…...

html中实用标签dl dt dd(有些小众的标签 但是很好用)
背景描述 html <dl> <dt> <dd>是一组合标签,他们与ol li、ul li标签很相似 但是他却是没有默认前缀并且有缩进的标签 使用方式与table表格的标签一致 使用方式 dt和dd是放于dl标签内,dt与dd处于dl下相同级。就是dt不能放入dd内&am…...

ONES 功能上新|ONES Copilot、ONES Wiki 新功能一览
ONES Copilot 可基于工作项的标题、描述、属性信息,对工作项产生的动态和评论生成总结。 针对不同类型的工作项,总结输出的内容有对应的侧重点。 应用场景: 在一些流程步骤复杂、上下游参与成员角色丰富的场景中,工作项动态往往会…...

实现Python将csv数据导入到Neo4j
目录 一、获取数据集 1.1 获取数据集 1.2 以“记事本”方式打开文件 1.3 另存为“UTF-8”格式文件 1.4 选择“是” 二、 打开Neo4j并运行 2.1 创建新的Neo4j数据库 2.2 分别设置数据库名和密码 编辑 2.3 启动Neo4j数据库 2.4 打开Neo4j数据库 2.5 运行查看该数据库…...

QML Rectangle组件
文章目录 前言主体**简单的矩形****渐变的矩形****带边框的矩形****圆角矩形****圆形 & 圆环** 总结 前言 在 QML 中,Rectangle 是一个常见且非常实用的元素,它允许开发者轻松创建矩形形状的图形。通过调整 Rectangle 的多种属性,我们不…...

uniapp开发app,cover-view不能隐藏,使用v-if,v-show都不行的解决办法
先上解决方案 在最后多写一个v-else <cover-view class"point-info" v-if"selectedPoint"><cover-view class"info-content"><cover-view class"info-item">。。。</cover-view><cover-view class"i…...

用adb命令给APP做压力测试,有什么不同?
压力测试 app做压力测试目的是模拟用户在使用软件时随意向软件发出指令,例如操作app的点击,滑动,返回等一系列随机事件,来检测app的承受能力 第一步:手机安装包需要待测的app 第二步:输入adb start-ser…...

netcore 集成Prometheus
一、安装包 <ItemGroup><PackageReference Include"prometheus-net" Version"8.2.1" /><PackageReference Include"prometheus-net.AspNetCore" Version"8.2.1" /> </ItemGroup> 二、添加代码 #region Pro…...

同城外卖系统源码扩展指南:搭建海外外卖APP平台详解
本篇文章,笔者将探讨如何基于同城外卖系统源码,搭建适合不同国家的海外外卖APP平台,涵盖多语言支持、支付接口对接、本地化适配等方面的实践经验和技术要点。 一、确定目标市场与用户需求 在开发海外外卖APP平台之前,首先需要深…...

JavaScript 中常见内置对象的知识点及示例总结
一、String(字符串)对象 知识点: 用于处理文本数据,它有许多内置的属性和方法来操作字符串,比如获取字符串长度、提取子字符串、替换字符等。字符串在 JavaScript 中是不可变的,即一旦创建,就不…...

CSSmodule的作用是什么
CSS Modules的作用主要体现在以下几个方面: 1. 解决全局样式污染问题 在传统的CSS管理方式中,样式定义通常是全局的,这很容易导致全局样式污染。当多个组件或页面共享同一个样式时,可能会出现样式冲突和覆盖的情况,从…...

python\shell\c++语法对比
语法区别举例: itempythonshellc变量定义a 10a10int a 10数组定义arr[1, add, 3]arr(1 a hello) declare -A arr([a]1 [b]2)int arr[] {1, 2, 3}if条件判断 if xxx: xxx elif xxx: xxx else: xxx if [ expressions ];then xxx e…...

优先队列【东北大学oj数据结构9-3】C++
优先队列 优先级队列是一种数据结构,其中保存了一组数据 S,其中每个元素都有一个键,并执行以下操作: insert(S, k):将元素k插入集合S extractMax(S):从S中取出S中key最大的元素并返回其值 创建一个程序&am…...

圣诞快乐(h5 css js(圣诞树))
一,整体设计思路 圣诞树h5(简易) 1.页面布局与样式: 页面使用了全屏的黑色背景,中央显示圣诞树,树形由三层绿色的三角形组成,每一层的大小逐渐变小。树干是一个棕色的矩形,位于三角…...

基于MATLAB的图像增强
目录 一、背景及意义介绍背景图像采集过程中的局限性 意义 二、概述三、代码结构及说明(一)整体结构(二)亮度增强部分(三)对比度增强部分(四)锐度增强部分 四、复现步骤(…...

大数据之Hbase环境安装
Hbase软件版本下载地址: http://mirror.bit.edu.cn/apache/hbase/ 1. 集群环境 Master 172.16.11.97 Slave1 172.16.11.98 Slave2 172.16.11.99 2. 下载软件包 #Master wget http://archive.apache.org/dist/hbase/0.98.24/hbase-0.98.24-hadoop1-bin.tar.gz…...

javaEE--计算机是如何工作的-1
目录 一.计算机的组成: 各组件的功能: 衡量cpu好坏的标准: 二.指令(instruction) 三.操作系统Operating System 四.进程/任务process/tesk 五.进程在系统中如何管理 1.进程在系统中的管理,从两个角度来分类: 2.进程控制块PCB(Process Control Block)) 3.P…...

vue.js 指令的修饰符
Vue.js 提供了一些指令修饰符,用于在指令的行为上添加额外的功能。下面详细解析一些常用的指令修饰符,并提供相应的代码实例。 .prevent:阻止默认事件 通过添加 .prevent 修饰符,可以阻止指令绑定的元素触发默认事件。 代码实例&a…...

基于java web在线商城购物系统源码+论文
一、环境信息 开发语言:JAVA JDK版本:JDK8及以上 数据库:MySql5.6及以上 Maven版本:任意版本 操作系统:Windows、macOS 开发工具:Idea、Eclipse、MyEclipse 开发框架:SpringbootHTMLjQueryMysq…...

Autosar入门_架构(Architecture)
上一篇 | 返回主目录 | 下一篇 架构(Architecture) 1 Autosar架构分层概述2 MCAL3 ECU抽象层4 复杂设备驱动5 服务层6 RTE7 应用软件层1 Autosar架构分层概述 整体架构分为三层:应用软件(APP)、实时运行环境(RTE)、基础软件(BSW)以下架构对BSW进行了细化,主要包含四…...

Altair: 轻松创建交互式数据可视化
Altair: 轻松创建交互式数据可视化 Altair 是一个基于 Vega-Lite 的 Python 数据可视化库,它旨在简化数据可视化的创建过程,尤其适用于统计图表的生成。Altair 强调声明式编码方式,通过简单的语法,用户能够快速创建复杂的交互式图…...

APM32F411使用IIS外设驱动es8388实现自录自播
前言: 从零开始学习I2s外设,配置Es8288寄存器实现录音播放。本文章使用主控芯片是APM32F411系类。音频相关的概念比较多,就不再次做过多的介绍,本文章只是简单实现边录边播功能。APM系类兼容st的芯片,所以用st的hal库来…...

RabbitMQ消息队列的笔记
Rabbit与Java相结合 引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId> </dependency> 在配置文件中编写关于rabbitmq的配置 rabbitmq:host: 192.168.190.132 /…...

JAVA没有搞头了吗?
前言 今年的Java程序员群体似乎承受着前所未有的焦虑。投递简历无人问津,难得的面试机会也难以把握,即便成功入职,也往往难以长久。于是,不少程序员感叹:互联网的寒冬似乎又一次卷土重来,环境如此恶劣&…...

【线性代数】理解矩阵乘法的意义(点乘)
刚接触线性代数时,很不理解矩阵乘法的计算规则,为什么规则定义的看起来那么有规律却又莫名其妙,现在参考了一些资料,回过头重新总结下个人对矩阵乘法的理解(严格来说是点乘)。 理解矩阵和矩阵的乘法&#x…...