Menu

  • Home
  • Blogs
  • Projects
logo
  • Home
  • Blog
  • Projects
logo
HomeBlogProjects

Built with:

  • AWS Lambda, S3, CloudFront
  • nextjs logo Next.js
© kenjiding 2025 All rights Reserved

The electron + react project implements the function of printing receipts

Views: 3526editDate: 8/4/2019

Tips:提醒:本文最后更新于 2581 天前,文中所描述的信息可能已发生改变,请谨慎使用。

Introduction

This article is aimed at developers with a certain understanding of Electron. For more information, please refer to the Electron official documentation.

Requirements

The company's project requires using Electron to call the system printer to print receipts.

Analysis

There are roughly two ways to print in Electron:

The first method involves using the webContents object of a window. With this method, you need to open a separate printing window, which can be hidden, but communication is relatively complex. The second method uses the webview element of a page for printing. The webview can be hidden within the calling page, making communication simpler. Both methods use the same approach to call the printing method.

This article implements silent printing using the second method.

Implementation

To implement printing, we first need to know which printers are available on our device. The method is: in the rendering thread, send an event to the main thread through Electron's ipcRenderer object to retrieve the printer list. (In this article, the rendering thread can be considered as a print.tsx file.)

    //(1) The main thread (electron.js) pseudo code is as follows:
    //引入electron
    import electron from 'electron';
    
    //Create a browser object
    const window = new electron.BrowserWindow({
        width,
        height,
        frame: false,
        show: false,
        backgroundColor: '#4b5b79',
        minWidth: 1024,
        minHeight: 768,
        webPreferences: { webSecurity: false },
      });
      
    // In the main thread, listen for the getPrinterList event sent from the rendering thread using the ipcMain object:
    electron.ipcMain.on('getPrinterList', (event) => {
        // The main thread gets the printer list
        const list = window.webContents.getPrinters();
        
        //  Send events to the rendering thread through webContents, and also pass the printer list to it.
        window.webContents.send('getPrinterList', list);
    });

print.tsx file

/**
 (2)Here is a pseudo code example for the rendering thread (print.tsx file) that
  includes the use of ipcRenderer to communicate with the main thread (ipcMain)
*/
import { ipcRenderer } from 'electron';

//In the rendering thread (print.tsx), you can use ipcRenderer to send a getPrinterList event to the main thread to request the list of printers
ipcRenderer.send('getPrinterList'); 

// Listen for the callback in the rendering thread after the main thread retrieves the list of printers.
ipcRenderer.once('getPrinterList', (event, data) => {
  //data就是打印机列表
  this.printList = data;
});

(Here comes the highlight) After obtaining the list of printers, we need to use the "webview" tag provided by Electron to format the receipt. What is "webview"? You can think of it as an "iframe" tag that displays the content you want to print.

Before using "webview", you need to create a new print.html file to display the content you want to print. Our project requirement is to draw the content to be printed on a canvas, then convert the canvas to an image resource (base64), and finally display it in the "webview". The specific steps are as follows: in the rendering thread (print.tsx), perform a series of logic to generate the base64 resource, and then use webview.send() to define a 'webview-print-render' event. This event can communicate with the print.html page and pass the base64 to print.html for display. Pseudo code for print.tsx is as follows:

printRender(imgsrc) {
  // get <webview>
  const webview = printWebview.current;
  // Send information to the page in <webview>
  webview.send('webview-print-render', {
    printName: this.printDeviceName, //Printer name
    imgSource: imgsrc, // base64 image
  });
}
				
<div style={{display: 'none'}}>
  <webview ref={printWebview} src="./xxxx/print.html" nodeintegration/>
</div>

print.html代码:

<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <style>
  //@The page style is used to set the style of the printed output, such as setting the margin for the receipt.
    @page {
      margin: 0px;
    }
  </style>
</head>
<body id='bd'>
</body>
<script>
    //import ipcRenderer
  const {ipcRenderer} = require('electron')
  
  // Listen to the webview-print-render event passed by the rendering thread
  ipcRenderer.on('webview-print-render', (event, deviceInfo) => {
    // Dynamically create an img tag and insert it into <body>. deviceInfo is the data passed by the rendering thread
    let html = '';
    html = `<img src="${deviceInfo.imgSource}"
     width="${deviceInfo.imgWidth}px"
     height="${deviceInfo.imgHeight}px">`;
    document.getElementById('bd').innerHTML = html;
    
    /**
      After inserting the image into the page, use the `sendToHost` method of the `ipcRenderer` object to communicate with the rendering thread,
      informing it that the content is ready for printing and to begin the printing process.
    */
    ipcRenderer.sendToHost('webview-print-do');
  });
</script>
</html>

Once the HTML file is created, include print.html in the webview tag (<webview src="./xxxx/print.html">). The webview tag needs to be explicitly defined in the print.tsx file, but it should be hidden using display: 'none', This is because we need the webview's DOM node to exist on the page, even though it is not visible.

useEffect(() => {
  const webview = tprintWebview.current;
  /**
    Listen for messages inside the `<webview>`, which means listening for events sent from `ipcRenderer.sendToHost` in `print.html`.
    When this event is successfully sent, the following callback will be triggered to execute the printing operation.
  */
  webview.addEventListener('ipc-message', (event) => {
    if (event.channel === 'webview-print-do') {
     /**
	If you receive an event named "webview-print-do" from the <webview>, 
	you should execute the webview.print method to print the content inside the <webview>.
     */
     webview.print({
        silent: true,
        printBackground: true,
        //  The name of the printer is one of the printer lists obtained at the beginning of this article.
        deviceName: 'xxx',
      },
     (data) => {
       // This callback is for the event after printing. If data is true, the printing is successful; if it's false, the printing fails.
      console.log('webview success', data);
     },
   )}
  });
}, []);
return <div style={{display: 'none'}}">
      <webview ref="printWebview" src="./xxxx/print.html" nodeintegration/>
   </div>

Here, the functionality of using Electron to call the printer has been implemented. However, this article did not cover many details and only provided a rough idea. If there are any mistakes in the writing, I apologize.

react electron html