如何通过Microsoft Print to PDF无对话框保存e.graphics绘制内容到指定文件夹
一键导出e.Graphics绘制内容为PDF(无弹窗)
实现方案
既然你已经基于PrintDocument完成了e.Graphics的绘制逻辑,直接复用现有代码,结合Microsoft Print to PDF打印机,通过系统API指定输出路径即可跳过保存对话框。以下是具体实现:
代码示例(WinForms环境)
1. 保留已有绘制逻辑
假设你已经有PrintDocument实例(如printDocument1),且PrintPage事件中完成了绘制:
private void printDocument1_PrintPage(object sender, PrintPageEventArgs e) { // 你的现有绘制代码,示例: e.Graphics.DrawString("测试内容", new Font("微软雅黑", 14), Brushes.Black, 150, 100); e.Graphics.DrawLine(Pens.Blue, 100, 50, 300, 50); // ...其他DrawImage/DrawLine等操作 }
2. 按钮点击事件:一键导出PDF
添加按钮的Click事件处理,直接指定目标PDF路径:
using System; using System.IO; using System.Printing; using System.Windows.Forms; using System.Runtime.InteropServices; private void btnSavePdf_Click(object sender, EventArgs e) { // 替换为你的目标PDF路径 string outputPdf = @"D:\SavedFiles\MyDrawing.pdf"; // 确保目标文件夹存在 string targetDir = Path.GetDirectoryName(outputPdf); if (!Directory.Exists(targetDir)) Directory.CreateDirectory(targetDir); // 初始化打印队列(指定Microsoft Print to PDF打印机) using (PrintQueue pdfQueue = new PrintQueue(new PrintServer(), "Microsoft Print to PDF")) { // 创建打印作业 using (PrintSystemJobInfo printJob = pdfQueue.AddJob("Export Drawing to PDF", printDocument1.DocumentName, false)) { // 关闭默认流,准备指定输出路径 printJob.JobStream.Close(); // 通过Win32 API设置PDF输出路径 SetPrintJobOutputPath(printJob.JobId, outputPdf); // 执行打印(即导出PDF) printDocument1.Print(); } } MessageBox.Show("PDF已保存至:" + outputPdf); } // Win32 API声明,用于修改打印作业参数 [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)] private static extern bool OpenPrinter(string printerName, out int printerHandle, ref PrinterDefaults defaults); [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)] private static extern bool ClosePrinter(int printerHandle); [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)] private static extern bool SetJob(int printerHandle, int jobId, int level, ref JobInfo2 jobInfo, int command); private struct PrinterDefaults { public int Datatype; public int DevMode; public int DesiredAccess; } private struct JobInfo2 { public int JobId; public string PrinterName; public string MachineName; public string UserName; public string Document; public string Datatype; public string Status; public int StatusValue; public int Priority; public int Position; public int TotalPages; public int PagesPrinted; public System.Runtime.InteropServices.ComTypes.FILETIME Submitted; public System.Runtime.InteropServices.ComTypes.FILETIME Started; public System.Runtime.InteropServices.ComTypes.FILETIME Completed; public string DriverName; public int Size; public int SecurityDescriptor; public int Attributes; public int PriorityClass; public int JobState; public int JobStateReasons; public int NumberOfJobStateReasons; public int JobStateReasonsArray; public int Error; public string PrintProcessor; public string Parameters; public string DriverData; public int DevMode; public string StatusMessage; public string SecurityDescriptorString; public string OutputFile; // 关键:指定输出PDF路径 public string PrintTicket; } private void SetPrintJobOutputPath(int jobId, string outputPath) { int printerHandle = 0; PrinterDefaults defaults = new PrinterDefaults(); defaults.DesiredAccess = 0x0004; // 管理员权限 // 打开打印机 if (OpenPrinter("Microsoft Print to PDF", out printerHandle, ref defaults)) { JobInfo2 jobInfo = new JobInfo2(); jobInfo.JobId = jobId; jobInfo.OutputFile = outputPath; // 设置作业属性,指定输出文件 SetJob(printerHandle, jobId, 2, ref jobInfo, 0x00000002); // JOB_CONTROL_SET_ATTRIBUTES ClosePrinter(printerHandle); } }
关键注意事项
- 打印机名称适配:中文系统中打印机名称可能是
"Microsoft 打印到 PDF",需对应修改代码中的打印机名称字符串。 - 权限要求:部分Windows版本需要程序以管理员权限运行,才能修改打印作业的输出路径。
- 文件覆盖:如果目标路径已存在同名PDF,默认会被覆盖,可添加
File.Exists(outputPdf)判断逻辑避免意外。 - 路径合法性:确保输出路径的文件夹存在,代码中已包含文件夹创建逻辑。
内容的提问来源于stack exchange,提问作者Etch
相关产品推荐
相关产品推荐

