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);
  });
相关推荐
willow19 分钟前
Promise由浅入深
javascript·promise
董员外22 分钟前
LangChain.js 快速上手指南:Tool的使用,给大模型安上了双手
前端·javascript·后端
用泥种荷花40 分钟前
【LangChain.js学习】 RAG(检索增强生成)完整实现解析
前端
willow1 小时前
Generator与Iterator
javascript
兔子零10241 小时前
Star-Office-UI-Node 实战:从 0 到 1 接入 OpenClaw 的多 Agent 看板
前端·ai编程
helloweilei1 小时前
一文搞懂Nextjs中的Proxy
前端·next.js
wuhen_n1 小时前
Pinia状态管理原理:从响应式核心到源码实现
前端·javascript·vue.js
陆枫Larry2 小时前
小程序 scroll-view 设置 padding 右侧不生效?用一层包裹解决
前端
晴殇i2 小时前
CommonJS 与 ES6 模块引入的区别详解
前端·javascript·面试
Selicens2 小时前
git批量删除本地多余分支
前端·git·后端