C#如何将自定义打印页与PdfiumViewer的PDF合并为同一份打印任务
实现方案
核心逻辑是自行创建统一的PrintDocument对象管理整个打印任务,第一页绘制二维码相关内容,第二页直接渲染PDF文件的内容,两个页面共用同一份打印配置,就能实现单任务连续打印。
具体实现步骤
- 先在类中定义两个成员变量,用来存储打印过程中需要复用的对象:
// 存储加载好的PDF文档对象 private PdfDocument _pdfToPrint; // 打印页码计数器,0代表第一页(二维码页),1代表第二页(PDF页) private int _currentPrintPageIndex = 0;
- 修改打印触发的方法,统一配置打印参数,绑定打印事件:
private void button1_Click(object sender, EventArgs e) { string pdfPath = @textBox1.Text; PrintCombinedDocument("M2020", "A4", pdfPath, 1); } public bool PrintCombinedDocument(string printer, string paperName, string pdfFilename, int copies) { try { // 预先加载要打印的PDF文档 _pdfToPrint = PdfDocument.Load(pdfFilename); _currentPrintPageIndex = 0; // 配置打印机参数 var printerSettings = new PrinterSettings { PrinterName = printer, Copies = (short)copies, }; // 配置页面参数 var pageSettings = new PageSettings(printerSettings) { Margins = new Margins(0, 0, 0, 0), }; foreach (PaperSize paperSize in printerSettings.PaperSizes) { if (paperSize.PaperName == paperName) { pageSettings.PaperSize = paperSize; break; } } // 自行创建打印文档对象,统一管理两页打印 using (var printDocument = new PrintDocument()) { printDocument.PrinterSettings = printerSettings; printDocument.DefaultPageSettings = pageSettings; printDocument.PrintController = new StandardPrintController(); // 绑定打印页处理事件 printDocument.PrintPage += CombinedPrintPageHandler; // 执行打印 printDocument.Print(); } // 释放PDF资源 _pdfToPrint.Dispose(); return true; } catch { _pdfToPrint?.Dispose(); return false; } }
- 实现统一的打印页处理方法,根据当前页码判断绘制内容:
private void CombinedPrintPageHandler(object sender, PrintPageEventArgs e) { if (_currentPrintPageIndex == 0) { // 第一页:绘制原来的二维码页内容,直接复用你原有的打印逻辑即可 string s2 = "Modified by: "; string s6 = "Author: " + author; string s4 = "Created: " + drawdate; QRCodeGenerator qrGenerator1 = new QRCodeGenerator(); QRCodeData qrCodeDataPrint = qrGenerator1.CreateQrCode(qrcodedata, QRCodeGenerator.ECCLevel.Q, false, false); Bitmap qrCodeImagePrint = (new QRCode(qrCodeDataPrint)).GetGraphic(20); Bitmap bmimg = new Bitmap(this.pictureBox2.Width, this.pictureBox2.Height); this.pictureBox2.DrawToBitmap(bmimg, new Rectangle(0, 0, this.pictureBox2.Width, this.pictureBox2.Height)); System.Drawing.Font f1 = new System.Drawing.Font("Arial", 5f, FontStyle.Bold, GraphicsUnit.Millimeter); System.Drawing.Font f2 = new System.Drawing.Font("Arial", 2f, GraphicsUnit.Millimeter); System.Drawing.Font f3 = new System.Drawing.Font("Arial", 3f, GraphicsUnit.Millimeter); System.Drawing.Font barc = new System.Drawing.Font("Code39Azalea", 36f, GraphicsUnit.Point); e.Graphics.PageUnit = GraphicsUnit.Millimeter; Pen blackPen = new Pen(Color.Black, 1f); Rectangle rect = new Rectangle(165, 35, 30, 30); Rectangle qrcodetest = new Rectangle(170, 40, 25, 25); Rectangle btmimg = new Rectangle(60, 140, 120, 120); Rectangle combox = new Rectangle(20, 145, 160, 40); e.Graphics.DrawImage(qrCodeImagePrint, qrcodetest); e.Graphics.DrawRectangle(blackPen, qrcodetest); e.Graphics.DrawString(this.procreq, f1, Brushes.Black, new Point(50, 5)); e.Graphics.DrawString(s1, f1, Brushes.Black, new Point(150, 70)); e.Graphics.DrawString(s1z, f2, Brushes.Black, new Point(150, 75)); e.Graphics.DrawString(qrissuedby, f2, Brushes.Black, new Point(20, 264)); e.Graphics.DrawString(s6, f2, Brushes.Black, new Point(20, 267)); e.Graphics.DrawString(s4, f2, Brushes.Black, new Point(20, 270)); e.Graphics.DrawString(s2, f2, Brushes.Black, new Point(20, 273)); e.Graphics.DrawString(s3, f2, Brushes.Black, new Point(20, 276)); e.Graphics.DrawString(s5, f2, Brushes.Black, new Point(20, 279)); e.Graphics.DrawString(this.notebox.Text, f3, Brushes.Black, combox); e.Graphics.DrawImage(bitmap1, btmimg); bmimg.Dispose(); bitmap1.Dispose(); // 标记还有下一页要打印 e.HasMorePages = true; _currentPrintPageIndex++; } else if (_currentPrintPageIndex == 1) { // 第二页:渲染PDF的第一页内容 e.Graphics.PageUnit = GraphicsUnit.Pixel; // 调用PdfiumViewer的Render方法把PDF页绘制到打印画布上 using (var pdfPage = _pdfToPrint.Pages[0]) { pdfPage.Render( e.Graphics, e.Graphics.VisibleClipBounds, new RectangleF(0, 0, pdfPage.Width, pdfPage.Height), GraphicsUnit.Pixel, true); } // 没有后续页面了 e.HasMorePages = false; _currentPrintPageIndex = 0; } }
注意事项
- 如果你的PDF有多页需要打印,可以在第二页的逻辑里再加页码判断,依次渲染所有PDF页即可
- 代码里用到的
author、drawdate、qrcodedata等变量都是你原有代码里的全局/成员变量,不需要修改直接复用即可 - 打印完成后记得释放PDF对象资源,避免内存泄漏
内容的提问来源于stack exchange,提问作者Andrew Taylor
相关产品推荐
相关产品推荐

