我现在学到的关于元文件的知识比我想知道的要多。
1. 某些Metafile
类的构造函数重载效果不佳,会在截断的 DPI 值上运行。
考虑以下:
protected Graphics GetNextPage(SizeF pageSize)
{
IntPtr deviceContextHandle;
Graphics offScreenBufferGraphics;
Graphics metafileGraphics;
MetafileHeader metafileHeader;
this.currentStream = new MemoryStream();
using (offScreenBufferGraphics = Graphics.FromHwnd(IntPtr.Zero))
{
deviceContextHandle = offScreenBufferGraphics.GetHdc();
this.currentMetafile = new Metafile(
this.currentStream,
deviceContextHandle,
new RectangleF(0, 0, pageSize.Width, pageSize.Height),
MetafileFrameUnit.Inch,
EmfType.EmfOnly);
metafileGraphics = Graphics.FromImage(this.currentMetafile);
offScreenBufferGraphics.ReleaseHdc();
}
return metafileGraphics;
}
如果您传入了SizeF
{ 8.5, 11 } 的 a,您可能会期望得到一个Metafile
{ rclFrame
21590, 27940 } 的 a。毕竟,将英寸转换为毫米并不难。但你可能不会。根据您的分辨率,GDI+ 似乎会在转换英寸参数时使用截断的 DPI 值。为了做到这一点,我必须自己完成百分之一毫米,GDI+ 只是通过它,因为这就是它本机存储在元文件头中的方式:
this.currentMetafile = new Metafile(
this.currentStream,
deviceContextHandle,
new RectangleF(0, 0, pageSize.Width * 2540, pageSize.Height * 2540),
MetafileFrameUnit.GdiCompatible,
EmfType.EmfOnly);
舍入错误 #1 已解决——rclFrame
我的元文件现在是正确的。
2.Graphics
实例录制到a的DPIMetafile
总是错误的。
看到metafileGraphics
我通过调用Graphics.FromImage()
元文件设置的变量了吗?好吧,似乎该Graphics
实例的 DPI 始终为 96 dpi。(如果我不得不猜测,它总是设置为逻辑DPI,而不是物理DPI 。)
您可以想象,当您绘制Graphics
在 96 dpi 下运行的实例并录制到Metafile
其标题中“记录”了 87.9231 dpi 的实例时,会产生欢闹。(我说“记录”是因为它是根据其他值计算得出的。)元文件的“像素”(请记住,存储在元文件中的 GDI 命令以像素为单位指定)更大,所以你诅咒和喃喃为什么你呼吁绘制一些东西一英寸长最终变成一英寸长。
解决方案是缩小Graphics
实例:
metafileGraphics = Graphics.FromImage(this.currentMetafile);
metafileHeader = this.currentMetafile.GetMetafileHeader();
metafileGraphics.ScaleTransform(
metafileHeader.DpiX / metafileGraphics.DpiX,
metafileHeader.DpiY / metafileGraphics.DpiY);
这不是胡说八道吗?但它似乎工作。
“舍入”错误 #2 已解决——当我说以 88 dpi 以“1 英寸”绘制某些东西时,该像素最好是 $%$^!记录为像素#88。
3.szlMillimeters
变化很大;远程桌面带来了很多乐趣。
因此,我们发现(根据 Mark 的回答)有时,Windows 会查询您的显示器的 EDID,并且实际上知道它的物理大小。GDI+HORZSIZE
在填写szlMillimeters
属性时很有帮助地使用这个(等)。
现在想象你回家调试远程桌面的这段代码。假设您的家用电脑恰好有一个 16:9 宽屏显示器。
显然,Windows 无法查询远程显示器的 EDID。所以它使用古老的默认值 320 x 240 毫米,这很好,只是它恰好是 4:3 的纵横比,现在完全相同的代码正在显示器上生成一个图元文件,据说该显示器没有方形物理像素:水平 DPI 和垂直 DPI 不同,我不记得上次看到这种情况是什么时候了。
我现在的解决方法是:“好吧,不要在远程桌面下运行它。”
4. 我使用的 EMF-to-PDF 工具在查看rclFrame
页眉时出现了舍入错误。
这是引发此问题的问题的主要原因。我的元文件一直都是“正确的”(好吧,在我解决了前两个问题之后是正确的),所有这些创建“高分辨率”元文件的搜索都是一个红鲱鱼。确实,在低分辨率显示设备上记录元文件时会丢失一些保真度;这是因为在元文件中指定的 GDI 命令是以像素为单位指定的。它是矢量格式并可以放大或缩小并不重要,当 GDI+ 决定将操作捕捉到哪个“像素”时,一些信息会在实际录制过程中丢失。
我联系了供应商,他们给了我一个更正的版本。
舍入错误 #3 已解决。
5. Windows 资源管理器中的“摘要”窗格恰好在显示计算的 DPI 时截断值。
恰好这个截断的值表示 EMF-to-PDF 工具在内部使用的错误值。除此之外,这个怪癖对讨论没有任何意义。
结论
由于我的问题是关于在设备上下文中使用 DPI 的问题,Mark's 是一个很好的答案。