这篇文章主要为大家介绍了C# 生成 EMF矢量图形文件详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
前言
公众号上有网友询问我如何生成 EMF 文件的问题:
本以为非常简单,我快速给出了解决方案:
var bitmap = new Bitmap(640, 480);
var g = Graphics.FromImage(bitmap);
g.DrawString("My IO", new Font(FontFamily.GenericSerif, 10), Brushes.Blue, 100, 100);
bitmap.Save("MyIO.emf",ImageFormat.Emf);
结果,网友告诉我,这是错误的:
用编辑器查看文件内容,发现实际生成的是PNG格式文件:
这是怎么回事呢?
原因
在官方文档上找到这样一段话:
当使用Save此方法将图形图像另存为Windows元文件格式 (WMF) 或增强的图元文件格式 (EMF) 文件时,生成的文件将改为保存为可移植网络图形 (PNG) 文件。发生此行为是因为.NET Framework的GDI+组件没有可用于将文件另存为 .wmf 或 .emf 文件的编码器。
不理解这样设计的原因,不支持应该抛出异常吧?!
实现
不过还好,从文档上我们也找到了解决方案,那就是使用Metafile类。
可是在实现时,又踩了不少坑。
创建实例失败
按照示例代码,使用文件名创建实例:
var metafile = new Metafile("MyIO.emf");
结果报了个通用异常,完全没有指导意义:
只好反编译代码查错。
发现,底层实现使用的GdipCreateMetafileFromFileAPI:
public Metafile(string filename)
{
Path.GetFullPath(filename);
SafeNativeMethods.Gdip.CheckStatus(SafeNativeMethods.Gdip.GdipCreateMetafileFromFile(filename, out IntPtr metafile));
SetNativeImage(metafile);
}
也就是说,参数必须是一个已存在的 EMF 文件名。
查看其他构造函数的实现,发现传递referenceHdc的构造函数使用的是GdipRecordMetafileFileNameAPI:
public Metafile(string fileName, IntPtr referenceHdc, EmfType type, string? description)
{
Path.GetFullPath(fileName);
SafeNativeMethods.Gdip.CheckStatus(SafeNativeMethods.Gdip.GdipRecordMetafileFileName(fileName, referenceHdc, type, IntPtr.Zero, MetafileFrameUnit.GdiCompatible, description, out IntPtr metafile));
SetNativeImage(metafile);
}
也就是说,这个 API 可以创建 EMF 文件。看来可以用。
而referenceHdc可以使用Graphics.GetHdc()得到。
于是,实现代码如下:
using (Graphics g1 = Graphics.FromHwnd(IntPtr.Zero))
{
using (var metafile = new Metafile("MyIO.emf", g1.GetHdc()))
{
using (Graphics g2 = Graphics.FromImage(metafile))
{
g2.DrawString("My IO", new Font(FontFamily.GenericSerif, 10), Brushes.Blue, 100, 100);
g2.DrawString("My IO", new Font(FontFamily.GenericSerif, 10), Brushes.Blue, 200, 200);
}
}
}
生成的确实是矢量图形文件:
绘制位置错误
可以明显看到,第一个My IO绘制的位置是错误的,绘制到了左上角,而不是(100, 100)。
再次查找构造函数,发现可以传递Rectangle参数:
修改实现代码如下:
using (Graphics g1 = Graphics.FromHwnd(IntPtr.Zero))
{
using (var metafile = new Metafile("MyIO.emf", g1.GetHdc(), new Rectangle(0, 0, 300, 300), MetafileFrameUnit.Pixel))
{
using (Graphics g2 = Graphics.FromImage(metafile))
{
g2.DrawString("My IO", new Font(FontFamily.GenericSerif, 10), Brushes.Blue, 100, 100);
g2.DrawString("My IO", new Font(FontFamily.GenericSerif, 10), Brushes.Blue, 200, 200);
}
}
}
这次总算成功了:
结论
后来发现,生成的图片实际是375 x 375像素,这应该是因为我的显示属性设置了缩放的原因(375 / 300 = 1.25):
以上就是C#生成EMF矢量图形文件示例详解的详细内容,更多关于C#生成EMF矢量图形文件的资料请关注得得之家其它相关文章!
本文标题为:C#生成EMF矢量图形文件示例详解
基础教程推荐
- linux – 如何在Debian Jessie中安装dotnet core sdk 2023-09-26
- unity实现动态排行榜 2023-04-27
- C# windows语音识别与朗读实例 2023-04-27
- C# 调用WebService的方法 2023-03-09
- ZooKeeper的安装及部署教程 2023-01-22
- C# List实现行转列的通用方案 2022-11-02
- 一个读写csv文件的C#类 2022-11-06
- C#控制台实现飞行棋小游戏 2023-04-22
- C#类和结构详解 2023-05-30
- winform把Office转成PDF文件 2023-06-14