1. 在主进程文件中,创建主窗口时,加入以下代码:
win.webContents.on("before-input-event", (event, input) => {
// console.log(input, 123);
if (input.control && input.shift && input.key.toLowerCase() === "i") {
// console.log("Pressed Control+I");
event.preventDefault(); // 阻止默认行为
}
});
全部代码展示:
import {
BrowserWindow,
BrowserWindowConstructorOptions,
ipcMain,
screen,
} from "electron";
import {
url,
appTitle,
preloadPath,
iconPath,
indexHtmlPath,
} from "./common/variables";
import { CustomChannel } from "../../globel/channelEvent";
interface IWindowsZi {
isMainWin: boolean; // 是否主窗口(当为true时会替代当前主窗口)
}
/* ======================= 定义一些窗口工具类中会使用到的常量,以及窗口顶级父类 ========================= */
// 默认窗口参数
export const defaultWindowConfig: BrowserWindowConstructorOptions &
IWindowConfig &
IWindowsZi = {
title: appTitle, //窗口标题
icon: iconPath, //窗口图标
width: 800, // 默认窗口宽度
height: 600, // 默认窗口高度
minWidth: 500, // 默认最小窗口宽度
minHeight: 500, // 默认最小窗口高度
autoHideMenuBar: true, // false: 显示默认菜单栏 true:不显示默认菜单栏
frame: false, // false: 去掉顶部导航,关闭按钮 true : 不去掉
modal: true,
show: false, // 启动后 显示不显示
isMainWin: false, //是否主窗口(当为true时会替代当前主窗口)
resizable: true, //是否支持调整窗口大小
webPreferences: {
devTools: true, // 是否打开调试模式
webviewTag: true,
preload: preloadPath,
nodeIntegration: true, //启用Node集成(是否完整的支持 node)
contextIsolation: false, //上下文隔离
},
};
/**
* 窗口管理顶级父类 定义一些属性,和公共方法
*/
export class WindowUtils {
group: Map<string, WindowGroup>; // 窗口组 key就是传入的key值,如果没传,则取窗口的id作为key值
main: BrowserWindow | any; // 主窗口的实例对象
/**
* 构造方法,初始化属性
*/
constructor() {
this.group = new Map();
}
// 显示 主窗口
listShow() {
this.main.show();
this.main.setSkipTaskbar(false);
// 单击通知区图标实现应用的显示或隐藏
// this.main.isVisible() ? this.main.hide() : this.main.show();
// this.main.isVisible() ? this.main.setSkipTaskbar(false) : this.main.setSkipTaskbar(true);
}
// 直接退出--前提条件
listMain() {
this.main = undefined;
}
// 事件监听处理
listen() {
// 窗口创建监听
ipcMain.handle(
CustomChannel.window_create,
(_, opt: IWindowConfig & IWindowsZi) => {
this.createWindows(opt);
}
);
// ipcMain.on('resize',(e)=>{
// let sizeData = ipcMain.getContentBounds()
// })
// 窗口位置修改监听
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);
}
);
}
/**
* 创建窗口
* @param windowConfig 窗口创建参数
*/
createWindows(windowConfig: IWindowConfig & IWindowsZi): BrowserWindow {
// 先通过key判断是否已窗口,有则聚焦
let windowKey = windowConfig.key;
let isMainWin = windowConfig.isMainWin; // 是否主窗口(当为true时会替代当前主窗口)
if (windowKey && windowKey.length > 0) {
/// 先从窗口组中取出记录
const wg: WindowGroup = this.group.get(windowKey);
if (wg) {
/// 根据记录中的窗口id获取窗口,假如存在该窗口,则聚焦该窗口
const oldWin = BrowserWindow.fromId(wg.windowId);
if (oldWin) {
oldWin.focus();
return oldWin;
}
}
}
// 创建窗口对象
const win: BrowserWindow = new BrowserWindow(
Object.assign({}, defaultWindowConfig, windowConfig)
);
// 将窗口的关键信息与key关联,存入窗口组中
windowKey = windowKey || win.id.toString();
this.group.set(windowKey, {
windowId: win.id,
webContentsId: win.webContents.id,
});
// 是否主窗口
if (isMainWin) {
if (this.main) {
// this.main.close();
this.main.destroy();
}
this.main = win;
}
// 根据当前环境加载页面,并传递参数
const param = windowConfig.param
? "?urlParamData=" + windowConfig.param
: "";
if (process.env.VITE_DEV_SERVER_URL) {
// 如果是开发环境,则直接访问本地跑起的服务,拼接对应的路由
win.loadURL(`${url}#${windowConfig.route}${param}`);
} else {
// 如果是线上环境,则加载html文件的路径,然后拼接路由
win.loadFile(indexHtmlPath, { hash: windowConfig.route + param });
}
win.webContents.openDevTools(); // 打开 开发者工具
// 绑定通用窗口事件
this.bindWindowEvent(win, windowConfig);
// console.log(this.group);
return win;
}
/**
* 绑定窗口事件
* @param win 窗口对象
* @param windowConfig 窗口创建参数
*/
bindWindowEvent(win: BrowserWindow | any, windowConfig: IWindowConfig) {
win.once("ready-to-show", () => {
win.show();
});
// 禁止 ctrl+shift+i 快捷键 打开 开发者工具
win.webContents.on("before-input-event", (event, input) => {
// console.log(input, 123);
if (input.control && input.shift && input.key.toLowerCase() === "i") {
// console.log("Pressed Control+I");
event.preventDefault(); // 阻止默认行为
}
});
// 监听窗口最大化
win.on('maximize', () => {
win.webContents.send("maximizeRender", { data: true });
});
// 监听窗口 取消最大化
win.on('unmaximize', () => {
win.webContents.send("maximizeRender", { data: false });
});
// 窗口关闭监听,此事件触发时,窗口即将关闭,可以拒绝关闭,此时窗口对象还未销毁
win.on("close", (e: any) => {
// let windowId = this.group.get(windowConfig.key).windowId;
if (this.main == win) {
win.webContents.send("mainSendToRender", { data: true });
e.preventDefault();
// win.destroy(); // 强制关闭窗口
} else {
// 设置窗口透明
if (win != null) {
win.setOpacity(0);
const key = windowConfig.key || win.id.toString();
this.group.delete(key);
}
}
}); // 尝试关闭窗口
// 此事件触发时,窗口已关闭,窗口对象已销毁
win.on("closed", () => {
// 在窗口对象被关闭时,取消订阅所有与该窗口相关的事件
if (win != null) {
win.removeAllListeners();
// 引用置空
win = null;
}
});
}
/**
* 修改窗口的位置
* @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;
}
}
}
/**
* 通过窗口事件获取发送者的窗口
* @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);
}
}
官方文档:键盘快捷键 | Electron 中文