廣西專業(yè)做網(wǎng)站的公司軟件排名工具
文章目錄
- 引入
- 實現(xiàn)效果
- 思路
- 聲明通用的定位對象
- 主進程模塊
- 渲染進程
- 測試效果
引入
demo項目地址
窗口工具類系列文章:
封裝窗口工具類【1】雛形
封裝窗口工具類【2】窗口組,維護窗口關系
封裝窗口工具類【3】控制窗口定向移動
很多時候,我們想直接讓某個窗口移動到邊角,例如居中、左上、右下等位置,electron沒有提供直接的api來實現(xiàn)這種操作,我們不妨基于electron的位置移動api進行封裝,實現(xiàn)窗口靈活的定向移動
實現(xiàn)效果
- 輸入key可以操作指定窗口,不輸入則操作本窗口
- 可以直接根據(jù)position參數(shù)快速控制窗口定向移動
- 輸入偏移量微調(diào)窗口
思路
electron位置相關api
electron獲取某個窗口所在屏幕的顯示對象
首先electron的窗口位置也是有(x,y)坐標,對應橫軸和縱軸,我們可以使用窗口移動api設置x和y,左上角就是[0,0],然后我們可以通過screen.getDisplayMatching(rect)
來獲取窗口所在屏幕的展示對象,從中可獲取屏幕的長寬和x,y等信息,接著咱們直接用這兩個數(shù)據(jù)做差即可:
假如屏幕用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 {....../*** ================= 窗口定位相關參數(shù) ================*//** 自定義定位類型 */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,用于需要微調(diào)定位的情況
- 這里我們把window作為參數(shù)傳入,而不是在方法內(nèi)部直接通過key去獲取,是為了方便后續(xù)其他在工具類中的位置修改操作方便調(diào)用
import {screen} from "electron";export class WindowUtils {...
/*** 修改窗口的位置* @param window 窗口對象* @param windowPosition 位置參數(shù)對象*/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 {.../*** 通過窗口事件獲取發(fā)送者的窗口* @param event ipc發(fā)送窗口事件*/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監(jiān)聽,來處理渲染進程的事件
- electron\main\windowUtils.ts
export class WindowUtils {...listen() {...// 窗口位置修改監(jiān)聽ipcMain.handle(CustomChannel.window_position_change,(_, windowPosition: IWindowPosition) => {// 假如傳了窗口的key,則獲取對應窗口,假如沒傳,則用發(fā)送事件的窗口const windowKey = windowPosition.windowKey;const cureentWin =windowKey && windowKey.length > 0? this.getWindowByKey(windowKey): this.getWindowByEvent(_);this.changeWindowPostion(cureentWin, windowPosition);});}
}
渲染進程
1.工具類中補充窗口位置修改方法調(diào)用
- src\utils\electronUtils.ts
/*** 修改當前窗口的位置* @param windowPosition 窗口位置修改參數(shù)*/
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可以操作指定窗口,不輸入則操作本窗口
- 可以直接根據(jù)position參數(shù)快速控制窗口定向移動
- 輸入偏移量微調(diào)窗口