C# 使用PdfiumViewer实现对PDF文档打印预览(二)

news/2024/11/29 3:57:58/

文章目录

      • 前言
      • 关于PdfiumViewer
      • 配置PdfiumViewer环境
      • PdfiumViewer 打开并预览本地的PDF文档
      • PdfiumViewer 预览PDF文件流
      • 小节
      • 附录

前言

想要对PDF文档进行预览和打印,实际上这个文档可以是存在的,也可以是一个PDF文件流(本地并没有PDF文件),找了一段时间发现有个特牛逼的开源组件PdfiumViewer,满足我这一切的需求,还可以自定义缩放,翻页的按钮。
但是这个组件需要和pdfium.dll配合使用,放在同一个路径下,运行在X86平台下。

关于PdfiumViewer

GitHub链接:https://github.com/pvginkel/PdfiumViewer

PdfiumViewer 是一个基于PDFium项目的PDF查看器,它提供了许多用于处理PDF文件的组件。承载了一个PdfRenderer控件,并添加一个工具栏老保存或打印PDF文件。
PdfDocument 用于呈现PDF文档的基类
PdfRenderer 是一个winform控件,可以渲染PdfDocument

PdfiumViewer需要PDFium库的支持,在Nuget包中是没有包含这个PDFium库的, 需要自己下载。界面大致是长这个样子,有保存、打印、放大、缩小菜单。
在这里插入图片描述

配置PdfiumViewer环境

使用VS自带的Nuget包管理器下载安装,这里我选择的是第一个。
在这里插入图片描述
然后再下载PDFium.dll,使用Nuget包管理器搜索并下载安装,这里x86_V64.v8-xfa的安装包。
在这里插入图片描述
在工程的 packages\PdfiumViewer.Native.x86.v8-xfa.2018.4.8.256\Build\x86路径下可以看到pdfium.dll, 就把pdfium.dllPdfiumViewer放在同一个路径下就可以使用了。
在这里插入图片描述

PdfiumViewer 打开并预览本地的PDF文档

创建一个winform工程,直接在.cs文件中添加PdfiumViewer即可。也可以直接把PdfiumViewer控件拖拽到工具栏,从工具栏添加这个组件,再编程。
方式1:直接打开已经存在本地的PDF文件。PdfDocument.Load的函数有四个重载,这是其中一个。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;using PdfiumViewer;namespace PdfiumViewerDemo
{public partial class Form1 : Form{public Form1(){InitializeComponent();// 加载PDF文档LoadPdfByDocument();}/// <summary>/// 加载本地PDF文档/// </summary>private void LoadPdfByDocument(){//创建一个PDFView控件PdfViewer pdfViewer1 = new PdfViewer();//设置位置和大小pdfViewer1.Location = new Point(5, 5);pdfViewer1.Size = new Size(200, 300);pdfViewer1.Dock = DockStyle.Fill;//将控件添加到界面上this.Controls.Add(pdfViewer1);//加载PDF文档pdfViewer1.Document = PdfDocument.Load(@"D:Demo.pdf");}}
}

运行代码的时候如果出现找不到“pdfium.dll”的异常,那么就是pdfium.dll没有和PdfViewer.dll放在同一目录下。
在这里插入图片描述
如果出现System.BadImageFormatException
HResult=0x8007000B
Message=试图加载格式不正确的程序。 (异常来自 HRESULT:0x8007000B)
Source=PdfiumViewer的异常,
在这里插入图片描述
那么很可能就是运行环境不对,应该更改为X86的运行环境。
在这里插入图片描述

运行效果:
在这里插入图片描述

PdfiumViewer 预览PDF文件流

PdfSharpHelper类具体代码如下,更多详细的介绍请移步c# 数据保存为PDF(三) (PdfSharp篇)
https://blog.csdn.net/weixin_40314351/article/details/127343819?spm=1001.2014.3001.5501


using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;using PdfSharp;
using PdfSharp.Drawing;
using PdfSharp.Pdf;namespace PdfiumViewerDemo
{public class PdfSharpHelper{// const string facename = "Times New Roman";static string fontName = "华文宋体"; //华文宋体 Arial//左右边距const int padding_leftRight = 30;//上下边距const int padding_topBottom = 30;/// <summary>/// 保存为文件流/// </summary>/// <param name="binary"></param>/// <returns></returns>public static MemoryStream SaveToStream(){PdfDocument doc = new PdfDocument();CreatePdfSharpPDF( doc);MemoryStream stream = new MemoryStream();doc.Save(stream);return stream;}/// <summary>/// 绘制功能码表头/// </summary>/// <param name="document"></param>/// <param name="page"></param>/// <param name="startY"></param>/// <returns></returns>private static float DrawPDFCodeTitle(PdfPage page, XGraphics gfx, float startY){float x = padding_leftRight;float y = startY;XFont Titlefont = new XFont(fontName, 9, XFontStyle.Bold);XSize size = gfx.MeasureString("Param", Titlefont);float endY = (float)size.Height * 2 + 5;//绘制标题gfx.DrawRectangle(XBrushes.LightCyan, new XRect(padding_leftRight, y,page.Width - 2 * padding_leftRight, endY));y += (float)size.Height * 2 + 1;gfx.DrawString(" Parameter", Titlefont, XBrushes.Black, x, y);x += (float)(page.Width * 0.32);gfx.DrawString("Value", Titlefont, XBrushes.Black, x, y);// x += (float)(page.Width * 0.098);// gfx.DrawString("Infomation", Titlefont, XBrushes.Black, x, y);x += (float)(page.Width * 0.31);gfx.DrawString("Setting", Titlefont, XBrushes.Black, x, y);gfx.DrawString("Default", Titlefont, XBrushes.Black, x, y - size.Height - 1);return (endY + startY);}/// <summary>/// 绘制页脚/// </summary>/// <param name="page">页面</param>/// <param name="gfx">画布</param>/// <param name="cur">当前页序号</param>/// <param name="total">总的页码数</param>private static void DrawPDFFooter(PdfPage page, XGraphics gfx, int cur, int total){//计算高度float endY = (float)page.Height - padding_topBottom;XFont Timefont = new XFont(fontName, 10, XFontStyle.Bold);//测量字符串大小XSize size = gfx.MeasureString("Drive Type/", Timefont);//绘制页脚gfx.DrawLine(new XPen(XColors.Black, 0.2f),padding_leftRight,endY,page.Width - padding_leftRight,endY);endY += 2 + (float)size.Height;//绘制信息String footerText = "Test for Windows(C) by 唠嗑一夏 Electric Corporation";gfx.DrawString(footerText, Timefont, XBrushes.Black, padding_leftRight,endY);Timefont = new XFont(fontName, 10, XFontStyle.Regular);//绘制页码数footerText = cur.ToString() + "/" + total.ToString();gfx.DrawString(footerText, Timefont, XBrushes.Black,(page.Width * 0.9), endY);}/// <summary>/// 数据表格/// </summary>/// <returns></returns>private static DataTable CreateData(){DataTable dt = new DataTable();DataColumn col1 = new DataColumn("Num", typeof(string));DataColumn col2 = new DataColumn("Name", typeof(string));DataColumn col3 = new DataColumn("Val", typeof(string));DataColumn col4 = new DataColumn("Des", typeof(string));DataColumn col5 = new DataColumn("Set", typeof(string));dt.Columns.Add(col1);dt.Columns.Add(col2);dt.Columns.Add(col3);dt.Columns.Add(col4);dt.Columns.Add(col5);Random random = new Random();List<string> nameList = new List<string>{"A", "BB", "CCC", "D","E", "F", "G","H","II","JJ", "LL", "M"};List<string> tempList = new List<string>{"dsd", "sdfdgvre", "Hello", "Gilrs","Today", "YYYY", "dfgre","GSD","fdgfer","Wesd", "DLG", "fsdahfi;o"};for (int i = 0; i < 10; i++){for (int j = 0; j < 10; j++){DataRow dr = dt.NewRow();dr[0] = "KK" + i.ToString("d2") + "." + j.ToString("d2");dr[1] = nameList[j];if (j % 3 == 0){dr[2] = random.NextDouble().ToString("f3");}else{dr[2] = i * j - random.Next(0, 30);}dr[3] = tempList[j];dr[4] = random.NextDouble().ToString("f2");//添加新行dt.Rows.Add(dr);}}return dt;}/// <summary>/// 创建PDF/// </summary>public static void  CreatePdfSharpPDF(PdfDocument doc){try{//获取测试数据DataTable dataTable = CreateData();//创建文档对象//  PdfDocument doc = new PdfDocument();//创建空页PdfPage page = doc.AddPage();//设置纸张大小page.Size = PageSize.A4;List<XGraphics> gfxList = new List<XGraphics>();//设置一个画布XGraphics gfx = XGraphics.FromPdfPage(page);gfxList.Add(gfx);const string fontName = "华文宋体";//设置字体XFont Titlefont = new XFont(fontName, 14, XFontStyle.Bold);XFont Timefont = new XFont(fontName, 12, XFontStyle.Regular);//绘制标题gfx.DrawString(" Parameter Settings Report(Program)", Titlefont, XBrushes.Black,new XRect(padding_leftRight, 30, page.Width - padding_leftRight, 30),XStringFormats.CenterLeft);//日期gfx.DrawString(DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"), Timefont, XBrushes.Black,new XRect(page.Width * 0.7, 30, page.Width * 0.3 - padding_leftRight, 30),XStringFormats.BottomRight);XPen linePen = new XPen(XColor.FromKnownColor(XKnownColor.Black), 0.1);//绘制线gfx.DrawLine(linePen,new XPoint(padding_leftRight, 60), new XPoint(page.Width - padding_leftRight, 60));//设置字体Titlefont = new XFont(fontName, 12, XFontStyle.Bold);Timefont = new XFont(fontName, 10, XFontStyle.Regular);//测量字体的大小XSize size = gfx.MeasureString("Program", Titlefont);XSize size2 = gfx.MeasureString("Drive Type/", Timefont);float y = 62;float endY = (float)size.Height + 4 + (float)size2.Height;//绘制矩形框和字符串gfx.DrawRectangle(XBrushes.LightCyan, new XRect(padding_leftRight, y, page.Width - 2 * padding_leftRight, endY));gfx.DrawString(" Program(Drive Selected / Connected)", Titlefont,XBrushes.Black, padding_leftRight, y, XStringFormat.TopLeft);y += 4 + (float)size.Height;gfx.DrawString(" Drive Type/Model: ", Timefont,XBrushes.Black, padding_leftRight, y, XStringFormat.TopLeft);y += 4 + (float)size2.Height;gfx.DrawLine(linePen,new XPoint(padding_leftRight, y), new XPoint(page.Width - padding_leftRight, y));y += 4;gfx.DrawString(" Project: ", Titlefont,XBrushes.Black, padding_leftRight, y, XStringFormat.TopLeft);y += 4 + (float)size.Height;gfx.DrawLine(linePen,new XPoint(padding_leftRight, y), new XPoint(page.Width - padding_leftRight, y));y += 4;Titlefont = new XFont(fontName, 11, XFontStyle.Bold);gfx.DrawString(" Information ", Titlefont,XBrushes.Black, padding_leftRight, y, XStringFormat.TopLeft);y += 100;//项目的标题y = DrawPDFCodeTitle(page, gfx, y) + 10;//绘制功能码的字体XFont funFont = new XFont(fontName, 9);XFont FunBoldFont = new XFont(fontName, 9, XFontStyle.Underline | XFontStyle.Bold);//字体的高度XSize funcSize = gfx.MeasureString("KK00.00", funFont);XSize funcBoldSize = gfx.MeasureString("KK00.00", FunBoldFont);int count = dataTable.Rows.Count;string str = "";string strBak = "";int j = 0;for (int i = 0; i < count; i++){//遍历功能码if ((y + funcSize.Height + 3) > (page.Height - padding_topBottom)){//换页page = doc.Pages.Add();page.Size = PageSize.A4;gfx = XGraphics.FromPdfPage(page);gfxList.Add(gfx);//绘制功能码表头y = DrawPDFCodeTitle(page, gfx, 10) + 10;}DataRow dataRow = dataTable.Rows[i];strBak = dataRow[0].ToString().Substring(0, 4);if (strBak != str){//绘制功能码组str = strBak;string converStr = strBak;j++;funcBoldSize = gfx.MeasureString(converStr, FunBoldFont);y += (float)funcBoldSize.Height + 6;gfx.DrawString(converStr, FunBoldFont, XBrushes.Black, padding_leftRight, y);y += 2;i--;continue;}// else{//绘制string tempStr = dataRow[0].ToString() + " " + dataRow[1].ToString();funcSize = gfx.MeasureString(tempStr, funFont);y += (float)funcSize.Height + 3;if ((y + funcSize.Height + 3) > (page.Height - padding_topBottom)){//换页page = doc.Pages.Add();page.Size = PageSize.A4;gfx = XGraphics.FromPdfPage(page);gfxList.Add(gfx);//绘制功能码表头y = DrawPDFCodeTitle(page, gfx, 10) + 10;}//序号+描述float widthX = padding_leftRight;gfx.DrawString(tempStr, funFont, XBrushes.Black, widthX, y);//当前值widthX += (float)(page.Width * 0.32);gfx.DrawString(dataRow[2].ToString(), funFont, XBrushes.Black, widthX, y);//设置值widthX += (float)(page.Width * 0.31);gfx.DrawString(dataRow[4].ToString(), funFont, XBrushes.Black, widthX, y);}}gfx = null;int Total = doc.PageCount;for (int i = 0; i < Total; i++){//绘制页脚DrawPDFFooter(page, gfxList[i], i + 1, Total);}// string path = "PdfSharpDemo.pdf";//  doc.Save(path);}catch (Exception ex){}}}}

将使用PdfSharp生成的PDF文件流,在PdfViewer中显示。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;using PdfiumViewer;namespace PdfiumViewerDemo
{public partial class Form1 : Form{public Form1(){InitializeComponent();// 加载PDF文档// LoadPdfByDocument();LoadPdfByStream();}/// <summary>/// 加载本地PDF文档/// </summary>private void LoadPdfByDocument(){//创建一个PDFView控件PdfViewer pdfViewer1 = new PdfViewer();//设置位置和大小pdfViewer1.Location = new Point(5, 5);pdfViewer1.Size = new Size(200, 300);pdfViewer1.Dock = DockStyle.Fill;//将控件添加到界面上this.Controls.Add(pdfViewer1);//加载PDF文档pdfViewer1.Document = PdfDocument.Load(@"D:Demo.pdf");}/// <summary>/// 加载PDF文件流/// </summary>private void LoadPdfByStream(){//创建一个PDFView控件PdfViewer pdfViewer1 = new PdfViewer();//设置位置和大小pdfViewer1.Location = new Point(5, 5);pdfViewer1.Size = new Size(200, 300);pdfViewer1.Dock = DockStyle.Fill;//将控件添加到界面上this.Controls.Add(pdfViewer1);//加载PDF文件流pdfViewer1.Document = PdfDocument.Load(PdfSharpHelper.SaveToStream());}}
}

在这里插入图片描述

小节

主要记录PdfiumViewer对PDF文档打印预览的两种方法,一种是直接打开加载PDF文档,另外一种是加载PDF文件流(与PdfSharp配合使用)。
PdfiumViewer组件主要是使用PdfDocument.Load来加载PDF文档。

附录

PdfiumViewer GitHub链接:https://github.com/pvginkel/PdfiumViewer

C# 使用自带的组件PrintPreviewDialog 和 PrintDocument实现打印预览(一)


http://www.ppmy.cn/news/61758.html

相关文章

5 系统数据文件和信息

5.1 口令文件 口令文件包含了下表中所示的各字段&#xff0c;这些字段包含在<pwd.h>中定义的passwd结构中。 /etc/passwd文件中的字段 说 明struct passwd 成员用户名char *pw_name加密口令char *pw_passwd数值用户IDuid_t pw_uid数值组IDgid_t pw_gid注释字段char *pw_g…

Linux 创建监控用户

1.创建用户和登录shell useradd -s /bin/bash monitor 2.修改用户密码 passwd monitor 3.创建用户shell执行命令目录 mkdir /home/monitor/.bin 4.root修改用户的shell配置文件 chown root. /home/monitor/.bash_profile chmod 755 /home/monitor/.bash_profile 5.修改ba…

数字化转型导师坚鹏:如何制定企业数字化转型年度培训规划

如何制定企业数字化转型年度培训规划 ——以推动企业数字化转型战略落地为核心&#xff0c;实现知行果合一 课程背景&#xff1a; 很多企业都在开展企业数字化转型培训工作&#xff0c;目前存在以下问题急需解决&#xff1a; 缺少针对性的企业数字化转型年度培训规划 不清…

Java8异步编程的技巧

以下是Java8异步编程的技巧&#xff1a; 1. CompletableFuture CompletableFuture是Java8中新增的一个类&#xff0c;它提供了一种简单而强大的异步编程方式。通过使用CompletableFuture&#xff0c;我们可以轻松地创建和组合异步任务&#xff0c;让代码更加简洁和易于维护。…

服装生产erp都有哪些功能?该如何选服装生产erp?

各位开服装工厂的老板是否遇到这些难题&#xff1a; 库存管理成本高&#xff0c;大量库存积压导致资金紧张&#xff1b; 车间用人成本高&#xff0c;工人工作效率低&#xff0c;浪费大量时间和资金成本&#xff1b; 生产、加工、成品出库等各环节无法顺畅衔接&#xff0c;补单困…

网络安全监管

网络安全监管 网络安全法律体系建设计算机犯罪、信息安全等基本概念我国立法体系及网络安全法我国的立法体系网络安全法出台背景基本概念安全法主要结构第一章 总则第二章 网络安全支持与促进第三章 网络运行安全第四章 网络信息安全第五章 监测预警与应急处置第六章 法律责任 …

Flutter——最详细(TextField)使用教程

TextField简介 文本输入框&#xff0c;拥有复杂的属性。可指定控制器、文字样式、装饰线、行数限制、游标样式等。监听输入框变动事件。 使用场景&#xff1a; 搜索框&#xff0c;输入账号密码等 属性作用controller输入框监听器decoration输入框装饰属性textAlign内容对齐方式…

SpringCloud-微服务Eureka服务注册中心

微服务&服务注册中心 前言一、微服务1.什么是微服务2.单体架构和微服务架构2.1.单体架构2.2.微服务架构 二、服务注册中心1.服务注册中心简介2.Eureka服务注册中心2.1.Eureka Server开发2.2 Eureka Client开发 3.Eureka的自我保护机制3.1.Eureka自我保护机制简介3.2.Eureka…