图元文件大小在控制台应用中不正确,在 Windows 窗体中正确



下面的代码应该生成一个增强型Windows图元文件(EMF),大小为200mm x 100mm,中心矩形为180mm x 80mm。从 Windows 窗体应用程序运行时,它可以工作。从控制台应用程序运行时,大小(或框架)不正确:它几乎正好是宽度和高度的两倍。

控制台应用和可能导致不同行为的 Windows 窗体应用之间有何不同?需要什么更改来校正 EMF 大小/frame_

两个应用程序都运行:

  • .NET Core 3.1(我尝试了.NET 6和.NET Framework,结果相同)
  • System.Drawing.Common 4.5.1(我尝试了更新的版本,结果相同)

我还尝试使用毫米作为页面和框架单位。它也有同样的效果。此外,尺寸又减少了 5%。在所有情况下,我都已将EMF文件插入Microsoft Word并从那里获取大小。

正如我所经历的那样,图元文件对使用的显示器有一种奇怪的依赖性,因此我使用比例为 200% 的 HiDPI 显示器可能是相关的。

using System;
using System.Drawing;
using System.Drawing.Imaging;
namespace MetafileDotNot
{
internal class Program
{
static void Main()
{
using (Graphics offScreenGraphics = Graphics.FromHwndInternal(IntPtr.Zero))
{
float mmToPixel = offScreenGraphics.DpiX / 25.4f;
using (Metafile metaFile = new Metafile(
"test.emf",
offScreenGraphics.GetHdc(),
new RectangleF(0, 0, 200 * mmToPixel, 100 * mmToPixel),
MetafileFrameUnit.Pixel,
EmfType.EmfPlusDual
))
using (Graphics graphics = Graphics.FromImage(metaFile))
{
graphics.PageUnit = GraphicsUnit.Pixel;
graphics.FillRectangle(Brushes.DarkBlue, new RectangleF(10 * mmToPixel, 10 * mmToPixel, 180 * mmToPixel, 80 * mmToPixel));
}
}
}
}
}

更新

如果我将显示的比例设置为 150%,则不正确的尺寸约为所需尺寸的 1.5 倍,而不是 2 倍。因此,它遵循显示缩放。

此外,控制台应用的offScreenGraphics.DpiX为 96,Windows 窗体应用的分别为 192 和 144,显示比例分别为 200% 和 150%。

感谢Hans Passant。他的链接超级有帮助。

因此,即使 EMF 是与分辨率无关的图形文件格式,屏幕(可能是主屏幕)的分辨率和 DPI 也会影响结果。基本上,EMF使用屏幕的物理单位。因此,对于HiDPI屏幕,这取决于屏幕缩放。

若要修复此问题,应用程序需要在DPI 感知模式下运行。请参阅下文,了解如何实现它。

如果在DPI 虚拟化模式下运行,则 EMF 帧的行为与 EMF 内容不同,并且结果不正确。这很奇怪,可能是一个错误。

我还注意到,没有一个结果符合Microsoft发布的EMF和EMF+标准。如果是这样,他们就不会在办公室Microsoft正常工作。现在它在Microsoft Word中很好地工作。

DPI 感知模式

在应用程序开始时调用此SetProcessDPIAware()

[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern bool SetProcessDPIAware();

或使用应用程序清单:

<?xml version="1.0" encoding="utf-8"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" >
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
<asmv3:application>
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<dpiAware>true</dpiAware>
</asmv3:windowsSettings>
</asmv3:application>
</assembly>

最新更新