Electron 实现自定义系统托盘菜单

效果如下:

其实实现自定义托盘菜单的本质上,就是开一个新窗口,下面直接给出核心代码。

javascript 复制代码
// 加载窗口
const loadWindow = (example, path) => {
  if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
    example.loadURL(process.env['ELECTRON_RENDERER_URL'] + (path ? `/#/${path}` : ''))
  } else {
    let obj = {}
    if (path) {
      obj.hash = path
    }
    example.loadFile(join(__dirname, '../renderer/index.html'), obj)
  }
}

const tww = 145
  const thh = 408
  trayWindow = new BrowserWindow({
    width: tww,
    height: thh,
    show: false,// 窗口创建后立即显示
    autoHideMenuBar: true,// 隐藏菜单栏
    frame: false,// 边框
    modal: true, // 模态窗口
    disableAutoHideCursor: true,// 禁止隐藏光标
    skipTaskbar: true,// 隐藏任务栏
    alwaysOnTop: true,// 窗口置顶
    resizable: false,// 禁止调整窗口大小
    webPreferences: {
      preload: join(__dirname, '../preload/index.js'),// 预加载脚本
      sandbox: false // 是否启用沙箱模式
    }
  })
  loadWindow(trayWindow, 'tray-menus')
  const tray = new Tray(icon)
  tray.setToolTip(`QQ: 1366666666\n声音: 开启\n消息提醒框: 开启\n会话消息: 任务栏头像闪动`)

  tray.on('click', () => {
    mainWindow.isVisible() ? mainWindow.hide() : mainWindow.show()
  })
  tray.on('right-click', (e, point) => {
    if (trayWindow.isVisible()) {
      return
    }
    // 显示弹窗
    trayWindow.show();
    // 获取托盘图标的位置
    const { x, y } = tray.getBounds();
    trayWindow.setPosition(x + 20, y - thh + 20); // 设置弹窗的位置
    // 设置定时器检查鼠标位置
    let timer = null;
    clearInterval(timer);
    timer = setInterval(() => {
      const screenPoint = screen.getCursorScreenPoint();
      const trayBounds = tray.getBounds();
      const windowBounds = trayWindow.getBounds();
      // 判断鼠标是否在托盘图标或弹窗范围内
      const isMouseOverTray = screenPoint.x >= trayBounds.x && screenPoint.x <= trayBounds.x + trayBounds.width &&
        screenPoint.y >= trayBounds.y && screenPoint.y <= trayBounds.y + trayBounds.height;
      const isMouseOverWindow = screenPoint.x >= windowBounds.x && screenPoint.x <= windowBounds.x + windowBounds.width &&
        screenPoint.y >= windowBounds.y && screenPoint.y <= windowBounds.y + windowBounds.height;
      // 如果鼠标不在托盘图标或弹窗范围内,隐藏弹窗
      if (!isMouseOverTray && !isMouseOverWindow) {
        clearInterval(timer);
        trayWindow.hide();
      }
    }, 100);
  });
相关推荐
打小就很皮...28 分钟前
HBuilder 发行Android(apk包)全流程指南
前端·javascript·微信小程序
集成显卡1 小时前
PlayWright | 初识微软出品的 WEB 应用自动化测试框架
前端·chrome·测试工具·microsoft·自动化·edge浏览器
前端小趴菜052 小时前
React - 组件通信
前端·react.js·前端框架
Amy_cx3 小时前
在表单输入框按回车页面刷新的问题
前端·elementui
dancing9993 小时前
cocos3.X的oops框架oops-plugin-excel-to-json改进兼容多表单导出功能
前端·javascript·typescript·游戏程序
后海 0_o3 小时前
2025前端微服务 - 无界 的实战应用
前端·微服务·架构
Scabbards_3 小时前
CPT304-2425-S2-Software Engineering II
前端
小满zs3 小时前
Zustand 第二章(状态处理)
前端·react.js
程序猿小D3 小时前
第16节 Node.js 文件系统
linux·服务器·前端·node.js·编辑器·vim
萌萌哒草头将军3 小时前
🚀🚀🚀Prisma 发布无 Rust 引擎预览版,安装和使用更轻量;支持任何 ORM 连接引擎;支持自动备份...
前端·javascript·vue.js