electron+vue3全家桶+vite项目搭建【29】封装窗口工具类【3】控制窗口定向移动

文章目录

    • 引入
    • 实现效果
    • 思路
    • 声明通用的定位对象
    • 主进程模块
    • 渲染进程
    • 测试效果

引入

demo项目地址
窗口工具类系列文章:
封装窗口工具类【1】雏形
封装窗口工具类【2】窗口组,维护窗口关系
封装窗口工具类【3】控制窗口定向移动

很多时候,我们想直接让某个窗口移动到边角,例如居中、左上、右下等位置,electron没有提供直接的api来实现这种操作,我们不妨基于electron的位置移动api进行封装,实现窗口灵活的定向移动

实现效果

  • 输入key可以操作指定窗口,不输入则操作本窗口
  • 可以直接根据position参数快速控制窗口定向移动
  • 输入偏移量微调窗口
    electron+vue3控制窗口定向移动柜

思路

electron位置相关api

electron获取某个窗口所在屏幕的显示对象

首先electron的窗口位置也是有(x,y)坐标,对应横轴和纵轴,我们可以使用窗口移动api设置x和y,左上角就是[0,0],然后我们可以通过screen.getDisplayMatching(rect)来获取窗口所在屏幕的展示对象,从中可获取屏幕的长宽和x,y等信息,接着咱们直接用这两个数据做差即可:

假如屏幕用s表示,窗口用w表示,窗口居中计算如下:

x = s.x + (s.width - w.width) / 2
y = s.y + (s.height - w.height) / 2

声明通用的定位对象

  • types\global.d.ts
/** 一些全局的对象补充声明 */
export {};
declare global {....../*** ================= 窗口定位相关参数 ================*//** 自定义定位类型 */type MyPosition =| "center" // 居中| "bottom-left" // 左下| "bottom-right" // 右下| "top-right" // 右上| "top-left"; // 左上/*** 注意,这里指的屏幕是当前窗口所在的屏幕【存在多个屏幕的情况下】*/interface IWindowPosition {windowKey?:string; // 窗口的key,不传就是修改本窗口的位置x?: number; // 屏幕左上角开始x轴位置y?: number; // 屏幕左上角开始y轴位置relativeWindowId?: number; // 相对于某个窗口的位置/默认相对于屏幕position?: MyPosition; // 相对于屏幕或窗口的位置offsetX?: number; // X轴偏移量offsetY?: number; // Y轴偏移量}
}

主进程模块

1.我们在窗口工具类中补充一个修改窗口位置的方法

  • electron\main\windowUtils.ts
  • 这里还补充了一个横纵轴的偏移量offsetX,offsetY,用于需要微调定位的情况
  • 这里我们把window作为参数传入,而不是在方法内部直接通过key去获取,是为了方便后续其他在工具类中的位置修改操作方便调用
import {screen} from "electron";export class WindowUtils {...
/*** 修改窗口的位置* @param window 窗口对象* @param windowPosition 位置参数对象*/changeWindowPostion(window: BrowserWindow, windowPosition: IWindowPosition) {// xy轴值let x = windowPosition.x;let y = windowPosition.y;if (x != null && y != null) {// 偏移量const offsetX = windowPosition.offsetX || 0;const offsetY = windowPosition.offsetY || 0;x = windowPosition.x + offsetX;y = windowPosition.y + offsetY;// 如果是相对于某个窗口的话,加上相对窗口的x、y坐标if (windowPosition.relativeWindowId) {const relativeWin = BrowserWindow.fromId(windowPosition.relativeWindowId);if (relativeWin) {x += relativeWin.getPosition()[0];y += relativeWin.getPosition()[1];}}window.setPosition(x, y);}// 如果有定位if (windowPosition.position) {// 偏移量const offsetX = windowPosition.offsetX || 0;const offsetY = windowPosition.offsetY || 0;const winBounds = window.getBounds();let relativeBounds = screen.getDisplayMatching(winBounds).bounds;if (windowPosition.relativeWindowId) {const relativeWin = BrowserWindow.fromId(windowPosition.relativeWindowId);if (relativeWin) {relativeBounds = relativeWin.getBounds();}}// 计算坐标switch (windowPosition.position) {case "center":window.setPosition(relativeBounds.x +(relativeBounds.width - winBounds.width) / 2 +offsetX,relativeBounds.y +(relativeBounds.height - winBounds.height) / 2 +offsetY);break;case "bottom-left":window.setPosition(relativeBounds.x + offsetX,relativeBounds.y +relativeBounds.height -winBounds.height +offsetY);break;case "bottom-right":window.setPosition(relativeBounds.x + relativeBounds.width - winBounds.width + offsetX,relativeBounds.y +relativeBounds.height -winBounds.height +offsetY);break;case "top-left":window.setPosition(relativeBounds.x + offsetX,relativeBounds.y + offsetY);break;case "top-right":window.setPosition(relativeBounds.x + relativeBounds.width - winBounds.width + offsetX,relativeBounds.y + offsetY);break;}}}
}

2.接着我们补充两个获取窗口的方法

  • electron\main\windowUtils.ts
export class WindowUtils {.../*** 通过窗口事件获取发送者的窗口* @param event ipc发送窗口事件*/getWindowByEvent(event: Electron.IpcMainInvokeEvent): BrowserWindow {const webContentsId = event.sender.id;for (const currentWin of BrowserWindow.getAllWindows()) {if (currentWin.webContents.id === webContentsId) {return currentWin;}}return null;}/*** 通过传入的key获取指定的窗口* @param key 窗口唯一key*/getWindowByKey(key: string): BrowserWindow {return BrowserWindow.fromId(this.group.get(key).windowId);}   
}

3.接着我们在listen方法中补充handle监听,来处理渲染进程的事件

  • electron\main\windowUtils.ts
export class WindowUtils {...listen() {...// 窗口位置修改监听ipcMain.handle(CustomChannel.window_position_change,(_, windowPosition: IWindowPosition) => {// 假如传了窗口的key,则获取对应窗口,假如没传,则用发送事件的窗口const windowKey = windowPosition.windowKey;const cureentWin =windowKey && windowKey.length > 0? this.getWindowByKey(windowKey): this.getWindowByEvent(_);this.changeWindowPostion(cureentWin, windowPosition);});}
}

渲染进程

1.工具类中补充窗口位置修改方法调用

  • src\utils\electronUtils.ts
/*** 修改当前窗口的位置* @param windowPosition 窗口位置修改参数*/
export function changeWindowPosition(windowPosition: IWindowPosition) {ipcRenderer.invoke(CustomChannel.window_position_change, windowPosition);
}

2.写一个功能展示的demo

  • src\components\demo\WindowPositionDemo.vue
<template><div class="mockDemo"><GoBack></GoBack><ul><li><el-input v-model="windowKey"></el-input></li><li><el-form inline><el-form-item label="距离左边距离"><el-input v-model="x"></el-input></el-form-item><el-form-item label="距离上边距离"><el-input v-model="y"></el-input></el-form-item><el-form-item label="距离左边偏移量"><el-input v-model="offsetX"></el-input></el-form-item><el-form-item label="距离上边偏移量"><el-input v-model="offsetY"></el-input></el-form-item><el-form-item><el-button@click="changeWindowPosition({x: Number.parseFloat(x),y: Number.parseFloat(y),offsetX: Number.parseFloat(offsetX),offsetY: Number.parseFloat(offsetY),windowKey,})">移动位置</el-button></el-form-item></el-form></li><li><el-button@click="changeWindowPosition({position: 'top-left',offsetX: Number.parseFloat(offsetX),offsetY: Number.parseFloat(offsetY),windowKey,})">左上</el-button><el-button@click="changeWindowPosition({position: 'top-right',offsetX: Number.parseFloat(offsetX),offsetY: Number.parseFloat(offsetY),windowKey,})">右上</el-button></li><li><el-button@click="changeWindowPosition({position: 'center',offsetX: Number.parseFloat(offsetX),offsetY: Number.parseFloat(offsetY),windowKey,})">居中</el-button></li><li><el-button@click="changeWindowPosition({position: 'bottom-left',offsetX: Number.parseFloat(offsetX),offsetY: Number.parseFloat(offsetY),windowKey,})">左下</el-button><el-button@click="changeWindowPosition({position: 'bottom-right',offsetX: Number.parseFloat(offsetX),offsetY: Number.parseFloat(offsetY),windowKey,})">右下</el-button></li></ul></div>
</template><script setup lang="ts">
import { changeWindowPosition } from "@/utils/electronUtils";
import { ref } from "vue";
const x = ref("0");
const y = ref("0");
const offsetX = ref("0");
const offsetY = ref("0");
const windowKey = ref("");
</script><style scoped>
ul {list-style: none;
}
</style>

测试效果

可以随心所欲的控制任何窗口到处定向移动了,是不是很酷 _三└(┐卍 ˘ω˘)卍

  • 输入key可以操作指定窗口,不输入则操作本窗口
  • 可以直接根据position参数快速控制窗口定向移动
  • 输入偏移量微调窗口
    electron+vue3控制窗口定向移动柜

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/720462.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【学习心得】网站运行时间轴(爬虫逆向)

一、网站运行时间轴 掌握网站运行时间轴&#xff0c;有助于我们对“请求参数加密”和“响应数据加密”这两种反爬手段的深入理解。 二、从网站运行的时间轴角度来理解两种反爬手段 1、加载HTML&#xff1a; 这是浏览器访问网站时的第一步&#xff0c;服务器会返回基础…

javascrip几种基本的设计模式

单例模式 ES5 function Duck1(name:string){this.namenamethis.instancenull }Duck1.prototype.getNamefunction(){console.log(this.name) }Duck1.getInstancefunction(name:string){if(!this.instance){this.instance new Duck1(name)} } const aDuck1.getInstance(a) const…

【系统架构设计师考试大纲】

曾梦想执剑走天涯&#xff0c;我是程序猿【AK】 目录 简述概要知识图谱考试目标考试要求考试题目题型分析计算机基础知识&#xff08;20%&#xff09;信息化战略与规划&#xff08;9%&#xff09;软件工程&#xff08;25%&#xff09;系统架构设计&#xff08;35%&#xff09;信…

⭐北邮复试刷题2369. 检查数组是否存在有效划分__DP (力扣每日一题)

2369. 检查数组是否存在有效划分 给你一个下标从 0 开始的整数数组 nums &#xff0c;你必须将数组划分为一个或多个 连续 子数组。 如果获得的这些子数组中每个都能满足下述条件 之一 &#xff0c;则可以称其为数组的一种 有效 划分&#xff1a; 子数组 恰 由 2 个相等元素…

初学arp欺骗

首先准备一台靶机这里用虚拟机的win10 已知网关与ip地址&#xff08;怕误伤&#xff09; 现在返回kali从头开始 首先探测自己的网关 然后扫内网存活的ip 发现有3台 用nmap扫一下是哪几台 成功发现我们虚拟机的ip 现在虚拟机可以正常访问网络 接下来直接开梭 ip网关 返回虚拟机…

win11部署自己的privateGpt(2024-0304)

什么是privateGpt? privategpt开源项目地址 https://github.com/imartinez/privateGPT/tree/main 官方文档 https://docs.privategpt.dev/overview/welcome/welcome PrivateGPT是一个可投入生产的人工智能项目&#xff0c;利用大型语言模型&#xff08;LLMs&#xff09;的…

智能通用平台(Intelligent General-purpose Platform)

根据2024年的最新人工智能技术发展趋势&#xff0c;我为您提出的项目需求表如下&#xff1a; 项目名称&#xff1a;智能通用平台&#xff08;Intelligent General-purpose Platform&#xff09;项目概述&#xff1a;结合最新的生成式人工智能、多模态学习和量子计算技术&#…

Windows Docker 部署 Jenkins

一、简介 今天介绍一下在 Windows Docker 中部署 Jenkins 软件。在 Windows Docker 中&#xff0c;分为两种情况 Linux 容器和 Windows 容器。Linux 容器是通常大多数使用的方式&#xff0c;Windows 容器用于 CI/CD 依赖 Windows 环境的情况。 二、Linux 容器 Linux 容器内部…

Linux系统宝塔面板搭建Typecho博客并实现公网访问本地网站【内网穿透】

文章目录 前言1. 安装环境2. 下载Typecho3. 创建站点4. 访问Typecho5. 安装cpolar6. 远程访问Typecho7. 固定远程访问地址8. 配置typecho 前言 Typecho是由type和echo两个词合成的&#xff0c;来自于开发团队的头脑风暴。Typecho基于PHP5开发&#xff0c;支持多种数据库&#…

Vue.js中的diff算法:让虚拟DOM更高效

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

【2024.03.05】定时执行专家V7.1最新版GUI界面 - 基于wxWidgets 3.2.4 + CodeBlocks + GCC9.2.0

《定时执行专家》是一款制作精良、功能强大、毫秒精度、专业级的定时任务执行软件。软件具有 25 种【任务类型】、12 种【触发器】触发方式&#xff0c;并且全面支持界面化【Cron表达式】设置。软件采用多线程并发方式检测任务触发和任务执行&#xff0c;能够达到毫秒级的执行精…

【深度学习笔记】5_5 LeNet

注&#xff1a;本文为《动手学深度学习》开源内容&#xff0c;部分标注了个人理解&#xff0c;仅为个人学习记录&#xff0c;无抄袭搬运意图 5.5 卷积神经网络&#xff08;LeNet&#xff09; 在3.9节&#xff08;多层感知机的从零开始实现&#xff09;里我们构造了一个含单隐藏…

182基于matlab的半监督极限学习机进行聚类

基于matlab的半监督极限学习机进行聚类&#xff0c;基于流形正则化将 ELM 扩展用于半监督&#xff0c;三聚类结果可视化输出。程序已调通&#xff0c;可直接运行。 182matlab ELM 半监督学习 聚类 模式识别 (xiaohongshu.com)

「滚雪球学Java」:JDBC(章节汇总)

&#x1f3c6;本文收录于「滚雪球学Java」专栏&#xff0c;专业攻坚指数级提升&#xff0c;助你一臂之力&#xff0c;带你早日登顶&#x1f680;&#xff0c;欢迎大家关注&&收藏&#xff01;持续更新中&#xff0c;up&#xff01;up&#xff01;up&#xff01;&#xf…

C# Winform画图绘制圆形

一、因为绘制的圆形灯需要根据不同的状态切换颜色,所以就将圆形灯创建为用户控件 二、圆形灯用户控件 1、创建用户控件UCLight 2、设值用户控件大小(30,30)。放一个label标签,AutoSize为false(不自动调整大小),Dock为Fill(填充),textaglign为居中显示。 private Color R…

微服务架构SpringCloud(2)

热点参数限流 注&#xff1a;热点参数限流默认是对Springmvc资源无效&#xff1b; 隔离和降级 1.开启feign.sentinel.enabletrue 2.FeignClient(fallbackFactory) 3.创建一个类并实现FallbackFactory接口 4.加入依赖 <!--添加Sentienl依赖--><dependency><gro…

机器学习笔记 大语言模型是如何运作的?一、语料库和N-gram模型

一、语料库 语言模型、ChatGPT和人工智能似乎无处不在。了解大型语言模型(LLM)“背后”发生的事情将是驾驭数字世界的关键。 首先在提示中键入一个单词,然后点击提交。您可以尝试新的提示,并根据需要多次重新生成响应。 这个我们称之为“T&C”的语言模型是在一…

店匠科技颁布 Shoplazza Awards:品牌出海迎历史性机遇,赋能品牌腾飞

在全球化的今天&#xff0c;中国品牌在全球市场的地位日益显著&#xff0c;品牌意识的提升推动了企业出海战略的全新转型。以全球电商市场发展为例&#xff0c;根据 ecommerceBD 数据&#xff0c;2023 年全球零售电子商务销售额预计 6.3 万亿美元&#xff0c;到 2026 年&#x…

我们距离AGI还有多远?

关于HBM那份纪要的其他反馈 上篇文章发了一篇HBM纪要小部分内容&#xff08;星球更新了另一部分&#xff09;&#xff0c;收到很多业内大佬们的反馈&#xff0c;包括颗粒计算、封装订单划分等等&#xff0c;以及是不是某通某电的一个专家。其中倒是出现一个非共识的说法&#…

【论文阅读】TensoRF: Tensorial Radiance Fields 张量辐射场

发表于ECCV2022. 论文地址&#xff1a;https://arxiv.org/abs/2203.09517 源码地址&#xff1a;https://github.com/apchenstu/TensoRF 项目地址&#xff1a;https://apchenstu.github.io/TensoRF/ 摘要 本文提出了TensoRF&#xff0c;一种建模和重建辐射场的新方法。不同于Ne…