如何在不指定文件名的情况下将FlowDocument打印为PDF
解决WPF中RTF转PDF自动指定文件名的问题
核心思路
Microsoft Print to PDF是虚拟打印机,要避免手动输入文件名,需直接向打印队列提交任务并指定输出路径,无需依赖PrintDialog的交互弹窗。
修改后的完整代码
using System.IO; using System.Windows; using System.Windows.Documents; using System.Printing; // 加载RTF到FlowDocument FlowDocument flowDocument = new FlowDocument(); TextRange textRange = new TextRange(flowDocument.ContentStart, flowDocument.ContentEnd); using (FileStream fileStream = File.Open(rtfTempName, FileMode.Open, FileAccess.Read, FileShare.Read)) { textRange.Load(fileStream, DataFormats.Rtf); } // 获取Microsoft Print to PDF打印机 var printers = new LocalPrintServer().GetPrintQueues(); var pdfPrinter = printers.FirstOrDefault(p => p.Name == "Microsoft Print to PDF"); if (pdfPrinter == null) { MessageBox.Show("未找到Microsoft Print to PDF打印机!"); return; } // 设置打印参数 var printTicket = pdfPrinter.DefaultPrintTicket.Clone(); printTicket.PageOrientation = PageOrientation.Landscape; // 自动生成PDF文件名(示例:基于原RTF文件名替换后缀) string outputPdfPath = Path.ChangeExtension(rtfTempName, ".pdf"); // 若需自定义文件名,可改用类似: // string outputPdfPath = $"{Path.GetFileNameWithoutExtension(rtfTempName)}_{DateTime.Now:yyyyMMddHHmmss}.pdf"; // 配置FlowDocument分页器 var paginator = ((IDocumentPaginatorSource)flowDocument).DocumentPaginator; paginator.PageSize = new PageMediaSize(PageMediaSizeName.ISOC4, printTicket.PageMediaSizeWidth, printTicket.PageMediaSizeHeight); // 提交打印任务生成PDF try { // AddJob方法指定输出路径,第三个参数false关闭打印设置弹窗 var printJob = pdfPrinter.AddJob("RTF转PDF任务", outputPdfPath, false); printJob.JobStream.Write(paginator, printTicket); printJob.JobStream.Close(); MessageBox.Show($"PDF已生成:{outputPdfPath}"); } catch (PrintSystemException ex) { MessageBox.Show($"生成PDF失败:{ex.Message}"); }
关键修改点说明
- 替换
PrintDialog.PrintDocument为PrintQueue.AddJob:直接传入自动生成的文件路径,彻底跳过手动输入环节 - 匹配分页器与打印票证尺寸:保证RTF内容的排版与PDF页面设置一致,避免内容截断或错位
- 异常捕获处理:覆盖权限不足、文件被占用等常见问题,提升程序稳定性
注意事项
- 确保程序拥有目标输出路径的写入权限
- 不同语言系统的打印机名称可能有差异(如中文系统为“Microsoft 打印到 PDF”),需适配对应名称
内容的提问来源于stack exchange,提问作者Fabrizio Ciavatta
相关产品推荐
相关产品推荐

