代码之家  ›  专栏  ›  技术社区  ›  Codo

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

  •  0
  • Codo  · 技术社区  · 3 年前

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

    控制台应用程序和Windows窗体应用程序之间有什么不同,它们可能导致不同的行为?纠正EMF大小/帧需要什么更改_

    两个应用程序都运行:

    • .NET Core 3.1(我尝试了.NET 6和.NET Framework,结果相同)
    • 系统绘画Common 4.5.1(我尝试了新版本,结果也一样)

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

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

    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%。

    0 回复  |  直到 3 年前
        1
  •  0
  •   Codo    3 年前

    多亏了汉斯·帕桑。他的 link 非常有帮助。

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

    要修复它,应用程序需要在 了解新闻部 模式见下文,了解如何实现它。

    如果在 DPI虚拟化 相反,EMF框架的行为与EMF内容不同,结果不正确。这很奇怪,可能是个虫子。

    我还注意到,所有结果都不符合微软发布的EMF和EMF+标准。如果是的话,它们就不能在微软Office中正常工作。现在,它在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>
    
    推荐文章