Published on

Electron 自定义窗口和右键菜单样式

Authors
  • Name
    Twitter

Electron 提供了强大的 API 来自定义应用的外观,包括窗口样式和上下文菜单(右键菜单)。本指南将详细介绍如何在 Electron 应用中实现这些自定义效果。

1. 自定义窗口样式

1.1 创建无边框窗口

首先,我们需要创建一个无边框窗口,这样我们就可以完全控制窗口的外观:

const { BrowserWindow } = require('electron');

function createWindow() {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    frame: false,
    transparent: true,
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: false
    }
  });

  win.loadFile('index.html');
}

1.2 添加自定义标题栏

index.html 中添加自定义标题栏:

<!DOCTYPE html>
<html>
<head>
  <title>自定义窗口</title>
  <style>
    body { margin: 0; font-family: Arial, sans-serif; }
    #titlebar {
      -webkit-app-region: drag;
      height: 30px;
      background: #333;
      color: #fff;
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 0 10px;
    }
    #titlebar button {
      -webkit-app-region: no-drag;
    }
  </style>
</head>
<body>
  <div id="titlebar">
    <span>我的应用</span>
    <div>
      <button id="minimize">-</button>
      <button id="maximize"></button>
      <button id="close">×</button>
    </div>
  </div>
  <div id="content">
    <!-- 应用内容 -->
  </div>
  <script src="renderer.js"></script>
</body>
</html>

1.3 实现窗口控制按钮功能

renderer.js 中添加控制逻辑:

const { ipcRenderer } = require('electron');

document.getElementById('minimize').addEventListener('click', () => {
  ipcRenderer.send('minimize-window');
});

document.getElementById('maximize').addEventListener('click', () => {
  ipcRenderer.send('maximize-window');
});

document.getElementById('close').addEventListener('click', () => {
  ipcRenderer.send('close-window');
});

在主进程中处理这些事件:

const { ipcMain } = require('electron');

ipcMain.on('minimize-window', () => {
  BrowserWindow.getFocusedWindow().minimize();
});

ipcMain.on('maximize-window', () => {
  const win = BrowserWindow.getFocusedWindow();
  win.isMaximized() ? win.unmaximize() : win.maximize();
});

ipcMain.on('close-window', () => {
  BrowserWindow.getFocusedWindow().close();
});

2. 自定义右键菜单样式

2.1 创建自定义右键菜单

在主进程中创建菜单模板:

const { Menu, MenuItem } = require('electron');

function createContextMenu() {
  const menu = new Menu();
  menu.append(new MenuItem({
    label: '复制',
    click: () => { /* 复制逻辑 */ }
  }));
  menu.append(new MenuItem({
    label: '粘贴',
    click: () => { /* 粘贴逻辑 */ }
  }));
  menu.append(new MenuItem({ type: 'separator' }));
  menu.append(new MenuItem({
    label: '自定义操作',
    click: () => { /* 自定义操作逻辑 */ }
  }));
  return menu;
}

2.2 显示自定义右键菜单

在渲染进程中监听右键点击事件:

window.addEventListener('contextmenu', (e) => {
  e.preventDefault();
  ipcRenderer.send('show-context-menu');
});

在主进程中处理显示菜单:

ipcMain.on('show-context-menu', (event) => {
  const menu = createContextMenu();
  menu.popup(BrowserWindow.fromWebContents(event.sender));
});

2.3 样式化右键菜单

要完全自定义右键菜单的样式,我们需要使用 HTML 和 CSS 创建自己的菜单:

<!-- 在 index.html 中 -->
<div id="custom-context-menu" style="display: none; position: fixed;">
  <ul>
    <li id="menu-copy">复制</li>
    <li id="menu-paste">粘贴</li>
    <li class="separator"></li>
    <li id="menu-custom">自定义操作</li>
  </ul>
</div>
#custom-context-menu {
  background: #fff;
  border: 1px solid #ccc;
  padding: 5px 0;
  box-shadow: 2px 2px 5px rgba(0,0,0,0.1);
}

#custom-context-menu ul {
  list-style-type: none;
  margin: 0;
  padding: 0;
}

#custom-context-menu li {
  padding: 5px 20px;
  cursor: pointer;
}

#custom-context-menu li:hover {
  background: #f0f0f0;
}

#custom-context-menu .separator {
  height: 1px;
  background: #ccc;
  margin: 5px 0;
}

然后在 JavaScript 中控制菜单的显示和行为:

const contextMenu = document.getElementById('custom-context-menu');

window.addEventListener('contextmenu', (e) => {
  e.preventDefault();
  contextMenu.style.display = 'block';
  contextMenu.style.left = `${e.clientX}px`;
  contextMenu.style.top = `${e.clientY}px`;
});

window.addEventListener('click', () => {
  contextMenu.style.display = 'none';
});

document.getElementById('menu-copy').addEventListener('click', () => {
  // 复制逻辑
});

// 其他菜单项的事件监听器...

3. 最佳实践

  1. 性能考虑:自定义窗口和菜单可能会影响性能,特别是在低端设备上。确保进行充分的测试。

  2. 跨平台兼容性:不同操作系统对窗口和菜单的期望可能不同。考虑为不同平台提供略微不同的样式。

  3. 可访问性:确保自定义 UI 元素是可访问的,支持键盘导航和屏幕阅读器。

  4. 响应式设计:确保自定义窗口在调整大小时仍然看起来不错。

  5. 主题支持:考虑实现暗色/亮色主题切换功能。

通过遵循这个指南,你应该能够为你的 Electron 应用创建独特的窗口和右键菜单样式。记住,好的设计不仅要美观,还要考虑用户体验和功能性。持续收集用户反馈并据此改进你的设计。