C# Windows窗体Panel转PDF遇依赖问题,求替代实现方案
希望将WinForms窗体中的Panel控件内容导出为PDF文件,尝试用iText7编写了代码,但运行时抛出异常,安装相关依赖时又出现大量错误,寻求其他实现Panel转PDF的方案。
所用代码
using System; using System.Data; using System.Windows.Forms; using iText.Kernel.Pdf; using iText.Layout; using iText.Layout.Element; using iText.IO.Image; using System.Drawing; using System.Drawing.Imaging; using System.IO; namespace PDFGeneratorApp { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void buttonPrintPDF_Click(object sender, EventArgs e) { Panel myPanel = panel1; string filePath = "file.pdf"; ExportPanelToPdf(panel1, filePath); } public static void ExportPanelToPdf(Panel panel, string filePath) { // 先将Panel捕获为位图 Bitmap bitmap = new Bitmap(panel.Width, panel.Height); panel.DrawToBitmap(bitmap, new Rectangle(0, 0, panel.Width, panel.Height)); // 将图像保存到流 using (MemoryStream stream = new MemoryStream()) { bitmap.Save(stream, ImageFormat.Png); byte[] imageBytes = stream.ToArray(); // 创建PDF文档 PdfWriter writer = new PdfWriter(filePath); PdfDocument pdf = new PdfDocument(writer); Document document = new Document(pdf); // 将图像添加到PDF ImageData imageData = ImageDataFactory.Create(imageBytes); iText.Layout.Element.Image image = new iText.Layout.Element.Image(imageData); document.Add(image); // 关闭文档 document.Close(); } } } }
抛出的异常
iText.Kernel.Exceptions.PdfException
HResult=0x80131500
Message=Unknown PdfException.
Source=itext.kernel
StackTrace:
at iText.Kernel.Pdf.SmartModePdfObjectsSerializer..ctor()
at iText.Kernel.Pdf.PdfWriter..ctor(Stream os, WriterProperties properties)
at iText.Kernel.Pdf.PdfWriter..ctor(String filename)
at PDFGeneratorApp.Form1.ExportPanelToPdf(Panel panel, String filePath) in C:\Users\CONSULTANT 2\source\repos\PDFGeneratorApp\Form1.cs:line 62
at PDFGeneratorApp.Form1.buttonPrintPDF_Click(Object sender, EventArgs e) in C:\Users\CONSULTANT 2\source\repos\PDFGeneratorApp\Form1.cs:line 46
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ButtonBase.WndProc(Message& m)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at PDFGeneratorApp.Program.Main() in C:\Users\CONSULTANT 2\source\repos\PDFGeneratorApp\Program.cs:line 19
最初抛出异常的调用栈:
iText.Bouncycastleconnector.BouncyCastleDefaultFactory.CreateIDigest(string)
iText.Kernel.Pdf.SmartModePdfObjectsSerializer.SmartModePdfObjectsSerializer()
内部异常1:
NotSupportedException: Either com.itextpdf:bouncy-castle-adapter or com.itextpdf:bouncy-castle-fips-adapter dependency must be added in order to use BouncyCastleFactoryCreator
方案1:使用PdfSharp(免费开源)
PdfSharp是.NET平台下的开源PDF库,无需额外加密依赖,操作简单。核心思路是先将Panel转为位图,再把位图插入PDF。
实现步骤:
- 通过NuGet安装
PdfSharp包(选择适配.NET Framework的版本)。 - 替换导出代码:
using PdfSharp.Drawing; using PdfSharp.Pdf; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Windows.Forms; public static void ExportPanelToPdf(Panel panel, string filePath) { // 捕获Panel为位图 Bitmap bitmap = new Bitmap(panel.Width, panel.Height); panel.DrawToBitmap(bitmap, new Rectangle(0, 0, panel.Width, panel.Height)); // 将位图转为PdfSharp可用的XImage using (MemoryStream ms = new MemoryStream()) { bitmap.Save(ms, ImageFormat.Png); ms.Position = 0; XImage xImage = XImage.FromStream(ms); // 创建PDF文档并设置页面尺寸匹配Panel PdfDocument document = new PdfDocument(); PdfPage page = document.AddPage(); page.Width = XUnit.FromPixels(bitmap.Width); page.Height = XUnit.FromPixels(bitmap.Height); // 将图像绘制到PDF页面 XGraphics gfx = XGraphics.FromPdfPage(page); gfx.DrawImage(xImage, 0, 0, page.Width, page.Height); // 保存并关闭文档 document.Save(filePath); document.Close(); } }
方案2:WinForms打印系统+虚拟PDF打印机
利用WinForms自带的PrintDocument控件,结合系统自带的虚拟PDF打印机(如Microsoft Print to PDF),直接将Panel内容"打印"为PDF,无需额外第三方库。
实现步骤:
- 在窗体中添加
PrintDocument控件(命名为printDocument1)。 - 编写导出逻辑:
private void buttonPrintPDF_Click(object sender, EventArgs e) { PrintDialog printDialog = new PrintDialog(); printDialog.Document = printDocument1; // 强制选择Microsoft Print to PDF(也可让用户自行选择) printDialog.PrinterSettings.PrinterName = "Microsoft Print to PDF"; if (printDialog.ShowDialog() == DialogResult.OK) { // 绑定打印事件,绘制Panel内容 printDocument1.PrintPage += (s, args) => { Bitmap bitmap = new Bitmap(panel1.Width, panel1.Height); panel1.DrawToBitmap(bitmap, new Rectangle(0, 0, panel1.Width, panel1.Height)); // 按页面尺寸缩放绘制图像 args.Graphics.DrawImage(bitmap, args.PageBounds); }; // 执行打印,输出为PDF文件 printDocument1.Print(); } }
注意:Windows 10及以上系统默认自带Microsoft Print to PDF,若未安装可在「设置-应用-可选功能」中添加。
方案3:使用Spire.PDF免费版
Spire.PDF免费版功能足够满足简单的图像转PDF需求,无需处理复杂依赖。
实现步骤:
- 通过NuGet安装
FreeSpire.PDF包。 - 编写导出代码:
using Spire.Pdf; using Spire.Pdf.Graphics; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Windows.Forms; public static void ExportPanelToPdf(Panel panel, string filePath) { Bitmap bitmap = new Bitmap(panel.Width, panel.Height); panel.DrawToBitmap(bitmap, new Rectangle(0, 0, panel.Width, panel.Height)); // 创建PDF文档并设置页面尺寸 PdfDocument doc = new PdfDocument(); PdfPage page = doc.Pages.Add(new SizeF(bitmap.Width, bitmap.Height)); PdfCanvas canvas = new PdfCanvas(page); // 将位图转为PdfImage并绘制到页面 using (MemoryStream ms = new MemoryStream()) { bitmap.Save(ms, ImageFormat.Png); PdfImage image = PdfImage.FromStream(ms); canvas.DrawImage(image, 0, 0, bitmap.Width, bitmap.Height); } // 保存PDF doc.SaveToFile(filePath); doc.Close(); }
内容的提问来源于stack exchange,提问作者Hex Heager

