You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 05:48:24