{T}

常用模块

菜单管理

菜单栏

下面先来学习不显示默认菜单,在主进程 main.js 中定义以下代码

javascript
const { BrowserWindow, app, Menu } = require('electron')
Menu.setApplicationMenu(null)

我们需要用到 Menu 模块、MenuItem 菜单项与 accelerator 快捷键知识

javascript
const { app, Menu } = require('electron')
 
//是否是苹果系统
const isMac = process.platform === 'darwin'
 
const template = [
  {
    label: '百度',
    submenu: [
      {
        label: '打开新窗口',
        click: () => {
          const win = new BrowserWindow({
            width: 300,
            height: 300,
          })
          win.loadURL('https://www.baidu.com')
        },
      },
      //分隔线
      {
        type: 'separator',
      },
      {
        label: '退出',
        click: async () => app.quit(),
        //定义快捷键
        accelerator: 'CommandOrControl+q',
      },
      //渲染进程触发主进程通信
      {
        click: () => mainWindow.webContents.send('update-counter', 1),
        label: 'Increment',
      },
      isMac
      ? { label: '关闭', role: 'close' }
      : { role: 'quit' },
    ],
  },
  {
    label: 'github',
    submenu: [
      {
        label: 'www.github.com',
      },
    ],
  },
]
 
const menu = Menu.buildFromTemplate(template)
Menu.setApplicationMenu(menu)

右键菜单

electron 可以定义快捷右键菜单,需要预加载脚本与主进程结合使用

main.js 主进程定义 ipc 事件,当 preload.js 触发事件时显示右键菜单

javascript
ipcMain.on('show-context-menu', (event) => {
  const popupMenuTemplate = [
    { label: '退出', click: () => app.quit() },
  ]
 
  const menu = Menu.buildFromTemplate(
    popupMenuTemplate,
  )
  menu.popup(
    BrowserWindow.fromWebContents(event.sender),
  )
})

preload.js 预加载脚本定义,用于触发右键事件,然后通过IPC调用主进程显示右键菜单

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

对话框

dialog 模块用于打开和保存文件、显示警告或确认消息框等功能,dialog 运行于主进程中

错误消息

使用 showErrorBox 可以控制显示错误消息,两个参数第一个参数是标题,第一个参数是显示内容

javascript
dialog.showErrorBox('通知', '你没有接收协议')

消息框

使用 showMessageBoxshowMessageBoxSync 显示消息框,返回结果是点击的按钮索引,然后你可以根据不同点击的按钮实现不同的业务。

建议使用 showMessageBox 异步方法处理消息框

javascript
app.whenReady().then(async () => {
  createWindow()
	const res = await dialog.showMessageBox({
    type: 'warning',
    title: '你要退出吗?',
    detail: '有问题吗?',
    buttons: ['取消', '退出'],
    //取消按钮的索引,使用esc根据索引调用取消按钮,默认为0,所以建议在buttons中将取消设置为第一个
    cancelId: 0,
    checkboxLabel: '接收协议',
    checkboxChecked: false,
  })
  
  if (!res.checkboxChecked) return dialog.showErrorBox('通知', '你没有接收协议')
  if (res.response == 1) app.quit()
})

选择文件

main.js 主进程,定义 IPC 通信事件 fileDialog 用于被渲染进程调用

javascript
...
app.whenReady().then(() => {
  createWindow()
  ipcMain.handle('fileDialog', () => {
    return dialog.showOpenDialog({
	    //对话框窗口的标题
      title: '选择文件',
      //选择文件、目录,并支持多选
      properties: [
        'openFile',
        'openDirectory',
        'multiSelections',
      ],
      //文件类型限制
      filters: [
        {
          name: 'Images',
          extensions: ['jpg', 'png', 'gif'],
        },
      ],
    })
  })
})
...

preload.js 预加载脚本,用于向主进程 main.js 发送 IPC 通信,调用 dialog 模块选择文件

javascript
const {
  contextBridge,
  ipcRenderer,
} = require('electron/renderer')
 
contextBridge.exposeInMainWorld('api', {
  selectFiles: () => {
    return ipcRenderer.invoke('fileDialog')
  },
})

renderer.js 渲染脚本,使用 IPC 通信通过 preload.js 调用主进程任务,并将dialog获取到的文件路径放入DOM #files 标签中

javascript
const bt = document.querySelector('#btn')
bt.addEventListener('click', async () => {
  const res = await api.selectFiles()
  document.querySelector('#files').innerHTML =
    res.filePaths.join('<br/>')
})

index.html 模板

  • #btn 按钮用于触发IPC通信
  • #files 标签用于显示 dialog 获取的文件列表
html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta
      http-equiv="Content-Security-Policy"
      content="default-src 'self'; script-src 'self'" />
    <meta
      http-equiv="X-Content-Security-Policy"
      content="default-src 'self'; script-src 'self'" />
    <title>houdunren</title>
  </head>
  <body>
    <button id="btn">选择文件</button>
    <div id="files"></div>
    <script src="renderer.js"></script>
  </body>
</html>

保存文件

使用 showSaveDialogSyncshowSaveDialog 接口用于保存文件

下面是使用 dialog 保存文件的示例

main.js 主进程,使用 dialog 模块选择文件保存位置,并调用 node 的 fs 模块写入文件

javascript
app.whenReady().then(() => {
  createWindow()
  ipcMain.handle('saveFileDialog', async () => {
    const res = await dialog.showSaveDialog({
      //默认文件名
      defaultPath: fileName,
      //对话框窗口的标题
      title: '保存壁纸图片',
      message: '',
      //允许创建目录
      properties: ['createDirectory']
    })
    writeFileSync(res.filePath, 'wenjainming')
    return res
  })
})

preload.js 预加载脚本,用于向主进程main.js发送IPC通信,调用 dialog 模块保存文件

javascript
const {
  contextBridge,
  ipcRenderer,
} = require('electron/renderer')
 
contextBridge.exposeInMainWorld('api', {
  saveFile: () => {
    return ipcRenderer.invoke('saveFileDialog')
  },
})

renderer.js 渲染脚本,使用 IPC 通信通过 preload.js 调用主进程任务,并将 dialog 保存文件

javascript
const bt = document.querySelector('#btn')
bt.addEventListener('click', async () => {
  const res = await api.saveFile()
})

index.html 模板,定义#btn按钮用于触发保存文件的 IPC 通信

html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta
          http-equiv="Content-Security-Policy"
          content="default-src 'self'; script-src 'self'" />
    <meta
          http-equiv="X-Content-Security-Policy"
          content="default-src 'self'; script-src 'self'" />
    <title>houdunren</title>
  </head>
  <body>
    <button id="btn">保存文件</button>
    <div id="files"></div>
    <script src="renderer.js"></script>
  </body>
</html>

通知消息

Mac、Windows、Linux 三个操作系统都为应用程序向用户发送通知提供了手段。 在主进程和渲染进程中,显示通知的技术不同的

对于渲染进程,Electron 方便地允许开发者使用 HTML5 通知 API 发送通知,要在主进程中显示通知,您需要使用 Notification 模块

渲染进程

渲染进程可以使用 HTML5 通知 API 发送通知

renderer.js

javascript
const bt = document.querySelector('#btn')
bt.addEventListener('click', async () => {
  new Notification('通知', {
    body: '记得每天多喝水',
  })
})

index.html

html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta
      http-equiv="Content-Security-Policy"
      content="default-src 'self'; script-src 'self'" />
    <meta
      http-equiv="X-Content-Security-Policy"
      content="default-src 'self'; script-src 'self'" />
    <title>houdunren</title>
  </head>
  <body>
    <button id="btn">发送通知</button>
    <div id="files"></div>
    <script src="renderer.js"></script>
  </body>
</html>

主进程

主进程发送通知需要使用 Notification 模块

下面是main.js主进程发送通知示例

javascript
app.whenReady().then(() => {
  createWindow()
  new Notification({
    title: '通知',
    body: '得每天多喝水',
  }).show()
})