当前位置: 首页 > news >正文

Electron Forge【实战】自定义菜单 -- 顶部菜单 vs 右键快捷菜单

效果预览

在这里插入图片描述
在这里插入图片描述

定义菜单 src/menu.ts

import { Menu, BrowserWindow, MenuItemConstructorOptions } from "electron";import { configManager } from "./config";
import en from "./language/en";
import zh from "./language/zh";type MessageSchema = typeof zh;
const messages: Record<string, MessageSchema> = {en,zh,
};// 创建一个通用的翻译函数
const createTranslator = () => {const config = configManager.get();return (key: string) => {const keys = key.split(".");let result: any = messages[config.language];for (const k of keys) {result = result[k];}return result as string;};
};// 顶部菜单
const createMenu = (mainWindow: BrowserWindow) => {const t = createTranslator();const template: MenuItemConstructorOptions[] = [{label: t("menu.app.myApp"),submenu: [{label: t("menu.app.newConversation"),accelerator: "CmdOrCtrl+N",click: () => {mainWindow.webContents.send("menu-new-conversation");},},{label: t("menu.app.settings"),accelerator: "CmdOrCtrl+,",click: () => {mainWindow.webContents.send("menu-open-settings");},},{ type: "separator" },{role: "quit",label: t("menu.app.quit"),},],},{label: t("menu.edit.title"),submenu: [{role: "undo",label: t("menu.edit.undo"),},{role: "redo",label: t("menu.edit.redo"),},{ type: "separator" },{role: "cut",label: t("menu.edit.cut"),},{role: "copy",label: t("menu.edit.copy"),},{role: "paste",label: t("menu.edit.paste"),},{role: "selectAll",label: t("menu.edit.selectAll"),},...(process.platform === "darwin"? ([{ type: "separator" as const },{label: t("menu.edit.speech.title"),submenu: [{role: "startSpeaking",label: t("menu.edit.speech.startSpeaking"),},{role: "stopSpeaking",label: t("menu.edit.speech.stopSpeaking"),},],},{role: "emoji",label: t("menu.edit.emoji"),},] as MenuItemConstructorOptions[]): []),],},{label: t("menu.view.title"),submenu: [{role: "reload",label: t("menu.view.reload"),},{role: "forceReload",label: t("menu.view.forceReload"),},{role: "toggleDevTools",label: t("menu.view.toggleDevTools"),},{ type: "separator" },{role: "resetZoom",label: t("menu.view.resetZoom"),},{role: "zoomIn",label: t("menu.view.zoomIn"),},{role: "zoomOut",label: t("menu.view.zoomOut"),},{ type: "separator" },{role: "togglefullscreen",label: t("menu.view.togglefullscreen"),},],},...(process.platform === "darwin"? [{role: "windowMenu" as const,},]: []),];const menu = Menu.buildFromTemplate(template);Menu.setApplicationMenu(menu);
};// 右键菜单
const createContextMenu = (win: BrowserWindow, id: number) => {const t = createTranslator();const template = [{label: t("contextMenu.deleteConversation"),click: () => {win.webContents.send("delete-conversation", id);},},];const menu = Menu.buildFromTemplate(template);menu.popup({ window: win });
};// 导出一个更新菜单的函数,在语言改变时调用
const updateMenu = (mainWindow: BrowserWindow) => {createMenu(mainWindow);
};export { createMenu, updateMenu, createContextMenu };

顶部菜单

加载顶部菜单 src/main.ts

import { createMenu } from "./menu";
  // 加载菜单createMenu(mainWindow);

添加 IPC 通信 src/preload.ts

  onMenuNewConversation: (callback: () => void) =>ipcRenderer.on("menu-new-conversation", () => callback()),onMenuOpenSettings: (callback: () => void) =>ipcRenderer.on("menu-open-settings", () => callback()),

全局监听菜单事件 src/App.vue

// 监听菜单事件
window.electronAPI.onMenuNewConversation(() => {router.push("/");
});window.electronAPI.onMenuOpenSettings(() => {router.push("/settings");
});

修改设置时,更新顶部菜单 src/ipc.ts

import { createContextMenu, updateMenu } from "./menu";
  ipcMain.handle("update-config", async (event, newConfig) => {const updatedConfig = await configManager.update(newConfig);// 如果语言发生变化,更新菜单if (newConfig.language) {updateMenu(mainWindow);}return updatedConfig;});

右键快捷菜单

目标元素上添加右键快捷菜单事件

src/components/ConversationList.vue

@contextmenu.prevent="showContextMenu(item.id)"
const showContextMenu = (id: number) => {window.electronAPI.showContextMenu(id);
};

添加 IPC 通信

src/preload.ts

  // 显示右键菜单showContextMenu: (id: number) => ipcRenderer.send("show-context-menu", id),// 删除会话onDeleteConversation: (callback: (id: number) => void) =>ipcRenderer.on("delete-conversation", (_event, id) => callback(id)),

src/ipc.ts

import { createContextMenu, updateMenu } from "./menu";
  // 弹出右键菜单ipcMain.on("show-context-menu", (event, id) => {const win = BrowserWindow.fromWebContents(event.sender);if (!win) return;createContextMenu(win, id);});

页面响应右键快捷菜单事件

src/components/ConversationList.vue

onMounted(() => {window.electronAPI.onDeleteConversation(async (id: number) => {await store.deleteConversation(id);if (store.selectedId === id) {store.selectedId = -1;router.push("/");}});
});

相关文章:

  • 力扣HOT100——207.课程表
  • pbchsim.c中main函数流程
  • 数据库有哪些特性是什么
  • 如何用GPU Instancing来优化树木草石重复模型
  • 【网络原理】 《TCP/IP 协议深度剖析:从网络基础到协议核心》
  • 产品VP简历模板案例
  • 基于大模型的膀胱肿瘤全周期诊疗方案研究报告
  • 在柯希霍夫积分法偏移成像中,旅行时计算中振幅和相位信息
  • 斯坦福RGA软件 老版本和兼容Windows 11版本可选
  • Linux指令
  • 产品经理.产品设计.产品设计工具
  • STM32F10X OLED屏幕点亮
  • 多类型文件集中查看系统
  • 计算机考研精炼 操作系统
  • 合并两个有序数组
  • 【网工第6版】第6章 网络安全②
  • 基于 IAR Embedded Workbench 的自研 MCU 芯片软件函数与变量内存布局优化精控方法
  • 临床回归分析及AI推理
  • Vue3 + TypeScript 实现 PC 端鼠标横向拖动滚动
  • ModStartCMS v9.4.0 AI
  • 迪卡侬回应出售中国业务30%股份传闻:始终扎根中国长期发展
  • 民生银行一季度净利127.42亿降逾5%,营收增7.41%
  • 83岁连丽如每周登台说书,还上了15堂连派评书课
  • 王毅:妥协退缩只会让霸凌者得寸进尺
  • 杭州一季度GDP为5715亿元,同比增长5.2%
  • 第1现场|无军用物资!伊朗港口爆炸已遇难40人伤1200人