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

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...

汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...
力扣-35.搜索插入位置
题目描述 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...
【生成模型】视频生成论文调研
工作清单 上游应用方向:控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...
【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制
使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下,限制某个 IP 的访问频率是非常重要的,可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案,使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...

【网络安全】开源系统getshell漏洞挖掘
审计过程: 在入口文件admin/index.php中: 用户可以通过m,c,a等参数控制加载的文件和方法,在app/system/entrance.php中存在重点代码: 当M_TYPE system并且M_MODULE include时,会设置常量PATH_OWN_FILE为PATH_APP.M_T…...

C# 表达式和运算符(求值顺序)
求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如,已知表达式3*52,依照子表达式的求值顺序,有两种可能的结果,如图9-3所示。 如果乘法先执行,结果是17。如果5…...
掌握 HTTP 请求:理解 cURL GET 语法
cURL 是一个强大的命令行工具,用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中,cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...