You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何使用Microsoft Print To PDF将EMF矢量图打印为PDF?

解决方案:直接绘制EMF矢量图到PrintDocument以生成矢量PDF

刚好之前做过类似的需求,我来给你说下正确的实现方式——你现在的问题出在把EMF转成Bitmap绘制,这就丢失了矢量信息,要直接在打印上下文的Graphics里绘制EMF文件,这样输出的PDF才会保持矢量属性,放大也不会模糊。

核心思路

不要将EMF转换为Bitmap,而是使用Metafile类直接加载EMF文件,然后在PrintPage事件的打印上下文Graphics对象上调用DrawImage方法。这样整个绘制过程会保留矢量数据,最终通过Microsoft Print To PDF生成的PDF文件里的内容也是矢量格式。

完整代码示例

下面是可直接复用的实现代码,包含EMF加载、打印配置和矢量绘制逻辑:

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Windows.Forms;

public class EmfVectorPdfPrinter
{
    private Metafile _targetEmf;

    public void PrintEmfToPdf(string emfFilePath)
    {
        // 加载EMF文件,注意使用using确保流资源释放
        using (var emfStream = new FileStream(emfFilePath, FileMode.Open, FileAccess.Read))
        {
            _targetEmf = new Metafile(emfStream);
        }

        var printDoc = new PrintDocument();
        
        // 配置Microsoft Print To PDF打印机
        printDoc.PrinterSettings.PrinterName = "Microsoft Print To PDF";
        printDoc.PrinterSettings.PrintToFile = true;
        // 可选:直接指定输出路径,不设置的话系统会弹出保存对话框
        printDoc.PrinterSettings.PrintFileName = @"D:\Output\VectorEmfOutput.pdf";

        // 绑定打印页事件
        printDoc.PrintPage += OnPrintPage;
        // 执行打印
        printDoc.Print();

        // 打印完成后释放EMF资源
        _targetEmf.Dispose();
    }

    private void OnPrintPage(object sender, PrintPageEventArgs e)
    {
        // 获取打印页面的可用区域
        var printBounds = e.PageBounds;
        // 获取EMF文件的原始尺寸
        var emfSize = new SizeF(_targetEmf.Width, _targetEmf.Height);

        // 计算缩放比例,保持宽高比且适配打印区域
        float scaleX = printBounds.Width / emfSize.Width;
        float scaleY = printBounds.Height / emfSize.Height;
        float finalScale = Math.Min(scaleX, scaleY);

        // 计算居中绘制的坐标
        float drawX = (printBounds.Width - emfSize.Width * finalScale) / 2;
        float drawY = (printBounds.Height - emfSize.Height * finalScale) / 2;

        // 直接在打印上下文绘制EMF,保留矢量信息
        e.Graphics.DrawImage(_targetEmf, drawX, drawY, emfSize.Width * finalScale, emfSize.Height * finalScale);

        // 标记没有更多打印页
        e.HasMorePages = false;
    }
}

关键细节说明

  • 矢量保留的核心:直接使用Metafile加载EMF并在打印Graphics上绘制,而非先转成BitmapBitmap是栅格图像,会丢失矢量数据,而Metafile会保留原始的矢量指令。
  • 缩放逻辑:通过计算最小缩放比例保证EMF完整适配打印页,同时保持宽高比避免变形,还可以根据需求调整为拉伸或固定尺寸。
  • 打印机配置:如果不需要预先指定PDF路径,删除PrintFileName的设置即可,系统会自动弹出保存对话框让用户选择路径。

注意事项

  • 确保项目引用了System.DrawingSystem.Windows.Forms程序集(WinForms项目默认已包含,控制台项目需手动添加引用)。
  • 要正确释放Metafile和文件流资源,避免内存泄漏。

内容的提问来源于stack exchange,提问作者L. Guthardt

火山引擎 最新活动