electron获取本地打印机并且实现打印

本文主要介绍了electron如何获取本地打印机,并且连接打印机进行打印

这里我用的是vue3,react或者vue2用户可自行根据代码来转换风格

1.打印机渲染在渲染进程,获取的话只能在主进程来获取

1.1 主进程获取-background.js

import 复制代码
let win
 
// 通过检查第二个实例启动时的事件来避免多个实例运行
const gotTheLock = app.requestSingleInstanceLock()
 
async function createWindow() {
  const config = {
    ...winState.winOptions,
    minWidth: 400, // 设置最小宽度
    webPreferences: {
      contextIsolation: false,
      enableRemoteModule: true,
      nodeIntegration: true,
      webSecurity: false, //允许跨域访问本地图片
      webviewTag: true,
    },
  }
  Menu.setApplicationMenu(null) // null值取消顶部菜单栏
 
  win = new BrowserWindow(config)
  if (process.env.WEBPACK_DEV_SERVER_URL) {
    // Load the url of the dev server if in development mode
    await win.loadURL(process.env.WEBPACK_DEV_SERVER_URL)
    if (!process.env.IS_TEST) win.webContents.openDevTools()
  } else {
    createProtocol('app')
    // Load the index.html when not in development
    win.loadURL('app://./index.html')
  }
  winState.manage(win)
}
 
app.on('ready', async () => {
  if (!gotTheLock) {
    app.quit()
  } else {
    app.on('second-instance', (event, commandLine, workingDirectory) => {
      if (win) {
        if (win.isMinimized()) {
          win.restore()
        }
        win.focus()
      }
    })
    createWindow()
 
// 在electron启动后注册所有的主进程ipc事件
    electronApiInit()
 
    win.on('closed', () => {
      win = null
    })
  }
 
})
 
// 主进程注册事件
function electronApiInit() {
  try {
    process.env.WEBPACK_DEV_SERVER_URL && win.setIcon(path.join(__dirname, `../public/favicon.png`))
 
    electronInit.initPrintList(win)
  } catch (error) {
    dialog.showErrorBox('ElectronApiInit', JSON.stringify(error.message))
  }
}

1.2 注册获取本地打印机事件

import 复制代码
export const initPrintList = (win) => {
  ipcMain.handle('getPrintList', async (event, isShowMessage) => {
    try {
       // 在background.js里把win对象传递进来,通过win的webContents的getPrintersAsync方法获取到本地打印机,在渲染进程进行读取
      const list = await win.webContents.getPrintersAsync()
      return list
    } catch (error) {
      console.log('error', error)
    }
  })
}

1.3渲染进程读取本地打印机数组(vue文件或者jsx文件)

javascript 复制代码
 
 
<div v-for="item in systemPrintList" :key="item.name">
        <div :class="['p-x-10', item.isActive ? 'header-active' : 'header-max']"  @click="setActiveItem(item)" >{{ item.name }}</div>
      </div>
 
const { ipcRenderer } = require('electron')
 
import {ref} from 'vue'
 
const printList = ref([])
 
    // 这个函数写到vue文件的methods里
async getPrintList({ commit }, data) {
      const list = await ipcRenderer.invoke('getPrintList', data)
      list.forEach((l) => {
       // isDefault字段是返回自带的,代表着当前哪台打印机处于活跃状态
        l.isActive = l.isDefault
      })
      printList.value = list
      console.log('list', list)
}
 
// 设置当前活跃的打印机
const setActiveItem = (item) => {
  printList.value.forEach((f) => {
    f.isActive = f.name === item.name
  })
}

到这步为止,已经可以获取到本地打印机,如果方便别的地方读取,可以存储到vuex/pinia/redux里

2.实现打印

electron的打印主要可以分为两种,一种是webContents的print方法,另一种是webview的打印,这里我们使用的是webContents的打印

2.1 获取webContents

要获取到webContents,首先需要获取到win。win在BrowserWindow可以拿到,因为打印是不能覆盖我们现有的electron页面,所以需要new一个新的BrowserWindow对象并且设置为show:false,我们可以封装一个print函数,打印的方法和函数之类的都可以写到这个函数里,这里我简单封装一个

// 复制代码
import { ipcMain, BrowserWindow } from 'electron'
export default function usePrint() {
  /**主窗体的win对象 */
  ipcMain.on('handle_print', (e, { htmlText, deviceName }) => {
    // 创建一个新的隐藏窗口,用于打印
    let printWindow = new BrowserWindow({ show: false, width: 1920, height: 1080, contextIsolation: false, enableRemoteModule: true, nodeIntegration: true, webSecurity: false })
    printWindow.loadURL('data:text/html,' + encodeURIComponent(htmlText))
    printWindow.webContents.print({ deviceName, silent: true })
  })
}

2.2 初始化主进程函数

// 复制代码
 
import { app, protocol, BrowserWindow, Menu, dialog } from 'electron'
import usePrint from './electron-service/ipc/usePrint'
 
let win
 
async function createWindow() {
  const config = {
    ...winState.winOptions,
    minWidth: 400, // 设置最小宽度
    webPreferences: {
      contextIsolation: false,
      enableRemoteModule: true,
      nodeIntegration: true,
      webSecurity: false, //允许跨域访问本地图片
      webviewTag: true,
    },
  }
  Menu.setApplicationMenu(null) // null值取消顶部菜单栏
 
  win = new BrowserWindow(config)
 
  winState.manage(win)
}
 
app.on('ready', async () => {
  if (!gotTheLock) {
    app.quit()
  } else {
    app.on('second-instance', (event, commandLine, workingDirectory) => {
      if (win) {
        if (win.isMinimized()) {
          win.restore()
        }
        win.focus()
      }
    })
    createWindow()
  }
// 这里初始化print
  usePrint()
})

2.3 渲染进程发送事件,主进程监听进行打印