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的图像增强
目录 一、背景及意义介绍背景图像采集过程中的局限性 意义 二、概述三、代码结构及说明(一)整体结构(二)亮度增强部分(三)对比度增强部分(四)锐度增强部分 四、复现步骤(…...
VB.net复制Ntag213卡写入UID
本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...
关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案
问题描述:iview使用table 中type: "index",分页之后 ,索引还是从1开始,试过绑定后台返回数据的id, 这种方法可行,就是后台返回数据的每个页面id都不完全是按照从1开始的升序,因此百度了下,找到了…...
学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...
图表类系列各种样式PPT模版分享
图标图表系列PPT模版,柱状图PPT模版,线状图PPT模版,折线图PPT模版,饼状图PPT模版,雷达图PPT模版,树状图PPT模版 图表类系列各种样式PPT模版分享:图表系列PPT模板https://pan.quark.cn/s/20d40aa…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...
Linux 下 DMA 内存映射浅析
序 系统 I/O 设备驱动程序通常调用其特定子系统的接口为 DMA 分配内存,但最终会调到 DMA 子系统的dma_alloc_coherent()/dma_alloc_attrs() 等接口。 关于 dma_alloc_coherent 接口详细的代码讲解、调用流程,可以参考这篇文章,我觉得写的非常…...
node.js的初步学习
那什么是node.js呢? 和JavaScript又是什么关系呢? node.js 提供了 JavaScript的运行环境。当JavaScript作为后端开发语言来说, 需要在node.js的环境上进行当JavaScript作为前端开发语言来说,需要在浏览器的环境上进行 Node.js 可…...
ArcPy扩展模块的使用(3)
管理工程项目 arcpy.mp模块允许用户管理布局、地图、报表、文件夹连接、视图等工程项目。例如,可以更新、修复或替换图层数据源,修改图层的符号系统,甚至自动在线执行共享要托管在组织中的工程项。 以下代码展示了如何更新图层的数据源&…...
