Excel如何计算在“如屏幕上显示”复制范围时生成的元数据的分辨率?

StackOverflow https://stackoverflow.com/questions/8317313

  •  25-10-2019
  •  | 
  •  

我有一些C#代码 http://bytes.com/topic/c-sharp/answers/572657-net-clipboard-metafiles 在以下两个设置下复制单元范围:

  • 如屏幕上所示,
  • 如图时所示.

当我查看由此产生的metafile的分辨率(记录在 Gets the resolution, in pixels-per-inch, of this Image object),根据复制方法,我得到不同的值。

  • 如图时所示 选项,分辨率为600,我相信这与我在Excel中拥有的DPI设置相对应。

  • 如屏幕上所示 设置,它吐出了类似的东西 Metafile.VerticalResolution = 72.08107Metafile.HorizontalResolution = 71.95952. 。在其他机器上,我看到这个值有很大差异(值约为111、130等)。

缩放水平似乎不会影响这一点。根据我的观察,这些值在一台计算机上保持一致,但在机器之间可能有所不同。

任何人都可以解释计算元数据分辨率时的逻辑Excel所遵循的 如屏幕上所示 模式?

更改Windows分辨率并测量了Metafile分辨率后,这是我生成的表(希望它看起来正确):

Width   Height  HorizontalResolution    VerticalResolution
1680    1050        71.95952                72.08107
1600    1024        72.05672                72.04874
1600    900         72.05672                71.88678
1360    768         71.96666                71.98228
1280    1024        71.9292                 72.04874
1280    960         71.9292                 71.9292
1280    800         71.9292                 72.05672
1280    768         71.9292                 71.98228
1280    720         71.9292                 71.99999
1152    864         72.07093                71.95278
1088    612         71.96666                71.96666
1024    768         72.04874                71.98228
960     600         71.9292                 71.88678
800     600         72.05672                71.88678

在虚拟机(同一物理机器)上运行类似的过程后,这些结果就是结果。比物理机本身更易变。这些数据可能没有用,但是认为我无论如何都会提供。

Width   Height  HorizontalResolution    VerticalResolution
1680    1050    133.35                  111.125
1280    800     101.6                   84.66666
1024    768     81.27999                81.27999
800     600     63.5                    63.5
有帮助吗?

解决方案

我的假设

我相信这与在LCD显示器上运行非本地分辨率有关。在“过去”中,CRT本身没有本地分辨率。因此,计算机不知道给定的监视器尺寸或纵横比的任何首选分辨率。使用较新的数字显示(LCD),计算机现在意识到正确安装的显示器的首选分辨率和纵横比。我的Windows 7机器显示了我LCD的本机分辨率旁边的“推荐”,然后显示其他2个等值比分辨率为黑色,其余的“不匹配”是不标记但可选的(导致我讨厌看到的挤压或拉伸外观在其他民族计算机上!)。

在CRT时代,建立了窗口中96和120的默认DPI。我的Windows 7机器甚至不再说DPI,它只是说“较小”,“中”,“较大”。

无论哪种方式,当您购买1920x1080或1920x1200的LCD显示器时,但将显示分辨率设置为较小的东西,则会导致转换因子。在接近72的非匹配水平和垂直分辨率的情况下,您的非本地显示分辨率可能不会垂直与缩放因子完全相同,因为它在水平上导致这种小差异。

如何检验我的假设

在每个测试机上,记录了配置分辨率和显示本机分辨率的操作系统。查看这两者之间的比率是否接近您的元素“按屏幕上”与96或120DPI之间的比率。我希望您在物理机器上进行此测试,以简单地排除使用远程台式机或虚拟机驱动程序进一步扩展的可能性。

如果解决方案没有立即明显,请进一步迈出一步,并记录DPI或“较小”,“中”和“较大”的操作和控制面板设置。 Windows XP的行为可能与Windows Vista/Windows 7不同。

您还可以多次重新运行同一台物理机上的测试,调整测试之间的配置显示分辨率并观察任何更改。如果我的假设是正确的,则应在同一物理机/显示组合上看到每个配置的显示分辨率的不同的元数据分辨率,并且该结果应该是可预测且可重复的(返回第一个分辨率应返回相同的元数据分辨率)

编辑#1

我找到了一篇出色的文章,讨论了物理DPI与逻辑DPI。对此有阅读: Windows中有96个DPI来自哪里?

因此,现在我建议的下一个测试是更改显示器!您是否有不同的品牌/尺寸/分辨率LCD监视器进行测试?您不需要上面的第一个测试就不需要太多线,因为我们已经建立了各种分辨率,往往会为同一显示器产生非常相似的DPI。只需测试一些常见的决议,包括显示器的本机分辨率和1024x768作为比较的“基准”。

同样,在Windows 7中浏览时,我确实在控制面板 - >显示中找到了“设置自定义文本大小(DPI)”链接,其中包括“使用Windows XP样式DPI缩放”选项。尽管我认为这不是主要问题,但好奇心使我对它的效果感兴趣,所以我想我会提到它。

编辑#2-解决!

您在元数据中看到的分辨率是显示器的物理DPI。我将在此处发布一些C#代码以测试自己:

[DllImport("user32.dll")]
static extern IntPtr GetDC(IntPtr hWnd);

[DllImport("user32.dll")]
static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDC);

[DllImport("gdi32.dll")]
static extern int GetDeviceCaps(IntPtr hdc, int nIndex);

public enum DeviceCap
{
    /// <summary>
    /// Device driver version
    /// </summary>
    DRIVERVERSION = 0,
    /// <summary>
    /// Device classification
    /// </summary>
    TECHNOLOGY = 2,
    /// <summary>
    /// Horizontal size in millimeters
    /// </summary>
    HORZSIZE = 4,
    /// <summary>
    /// Vertical size in millimeters
    /// </summary>
    VERTSIZE = 6,
    /// <summary>
    /// Horizontal width in pixels
    /// </summary>
    HORZRES = 8,
    /// <summary>
    /// Vertical height in pixels
    /// </summary>
    VERTRES = 10,
    /// <summary>
    /// Number of bits per pixel
    /// </summary>
    BITSPIXEL = 12,
    /// <summary>
    /// Number of planes
    /// </summary>
    PLANES = 14,
    /// <summary>
    /// Number of brushes the device has
    /// </summary>
    NUMBRUSHES = 16,
    /// <summary>
    /// Number of pens the device has
    /// </summary>
    NUMPENS = 18,
    /// <summary>
    /// Number of markers the device has
    /// </summary>
    NUMMARKERS = 20,
    /// <summary>
    /// Number of fonts the device has
    /// </summary>
    NUMFONTS = 22,
    /// <summary>
    /// Number of colors the device supports
    /// </summary>
    NUMCOLORS = 24,
    /// <summary>
    /// Size required for device descriptor
    /// </summary>
    PDEVICESIZE = 26,
    /// <summary>
    /// Curve capabilities
    /// </summary>
    CURVECAPS = 28,
    /// <summary>
    /// Line capabilities
    /// </summary>
    LINECAPS = 30,
    /// <summary>
    /// Polygonal capabilities
    /// </summary>
    POLYGONALCAPS = 32,
    /// <summary>
    /// Text capabilities
    /// </summary>
    TEXTCAPS = 34,
    /// <summary>
    /// Clipping capabilities
    /// </summary>
    CLIPCAPS = 36,
    /// <summary>
    /// Bitblt capabilities
    /// </summary>
    RASTERCAPS = 38,
    /// <summary>
    /// Length of the X leg
    /// </summary>
    ASPECTX = 40,
    /// <summary>
    /// Length of the Y leg
    /// </summary>
    ASPECTY = 42,
    /// <summary>
    /// Length of the hypotenuse
    /// </summary>
    ASPECTXY = 44,
    /// <summary>
    /// Shading and Blending caps
    /// </summary>
    SHADEBLENDCAPS = 45,

    /// <summary>
    /// Logical pixels inch in X
    /// </summary>
    LOGPIXELSX = 88,
    /// <summary>
    /// Logical pixels inch in Y
    /// </summary>
    LOGPIXELSY = 90,

    /// <summary>
    /// Number of entries in physical palette
    /// </summary>
    SIZEPALETTE = 104,
    /// <summary>
    /// Number of reserved entries in palette
    /// </summary>
    NUMRESERVED = 106,
    /// <summary>
    /// Actual color resolution
    /// </summary>
    COLORRES = 108,

    // Printing related DeviceCaps. These replace the appropriate Escapes
    /// <summary>
    /// Physical Width in device units
    /// </summary>
    PHYSICALWIDTH = 110,
    /// <summary>
    /// Physical Height in device units
    /// </summary>
    PHYSICALHEIGHT = 111,
    /// <summary>
    /// Physical Printable Area x margin
    /// </summary>
    PHYSICALOFFSETX = 112,
    /// <summary>
    /// Physical Printable Area y margin
    /// </summary>
    PHYSICALOFFSETY = 113,
    /// <summary>
    /// Scaling factor x
    /// </summary>
    SCALINGFACTORX = 114,
    /// <summary>
    /// Scaling factor y
    /// </summary>
    SCALINGFACTORY = 115,

    /// <summary>
    /// Current vertical refresh rate of the display device (for displays only) in Hz
    /// </summary>
    VREFRESH = 116,
    /// <summary>
    /// Horizontal width of entire desktop in pixels
    /// </summary>
    DESKTOPVERTRES = 117,
    /// <summary>
    /// Vertical height of entire desktop in pixels
    /// </summary>
    DESKTOPHORZRES = 118,
    /// <summary>
    /// Preferred blt alignment
    /// </summary>
    BLTALIGNMENT = 119
}

private void GetScreenInfo()
{
    IntPtr sdc = IntPtr.Zero;
    try
    {
        //Get the Screen Device Context
        sdc = GetDC(IntPtr.Zero);

        // Get the Screen Devive Context Capabilities Information
        Console.WriteLine(string.Format("Size: {0} mm X {1} mm", GetDeviceCaps(sdc, (int)DeviceCap.HORZSIZE), GetDeviceCaps(sdc, (int)DeviceCap.VERTSIZE)));
        Console.WriteLine(string.Format("Desktop Resolution: {0}x{1}", GetDeviceCaps(sdc, (int)DeviceCap.DESKTOPHORZRES), GetDeviceCaps(sdc, (int)DeviceCap.DESKTOPVERTRES)));
        Console.WriteLine(string.Format("Logical DPI: {0}x{1}", GetDeviceCaps(sdc, (int)DeviceCap.LOGPIXELSX), GetDeviceCaps(sdc, (int)DeviceCap.LOGPIXELSY)));

        //Remember: Convert Millimeters to Inches 25.4mm = 1 inch
        double PhsyicalDPI_X = GetDeviceCaps(sdc, (int)DeviceCap.DESKTOPHORZRES) * 25.4 / GetDeviceCaps(sdc, (int)DeviceCap.HORZSIZE);
        double PhsyicalDPI_Y = GetDeviceCaps(sdc, (int)DeviceCap.DESKTOPVERTRES) * 25.4 / GetDeviceCaps(sdc, (int)DeviceCap.VERTSIZE);
        Console.WriteLine(string.Format("Physical DPI: {0}x{1}", PhsyicalDPI_X, PhsyicalDPI_Y));

    }
    finally
    {
        ReleaseDC(IntPtr.Zero, sdc);
    }
}

我的显示上的此代码输出以下内容:

  • 尺寸:677毫米x 381毫米
  • 桌面分辨率:1920x1080
  • 逻辑DPI:96x96
  • 物理DPI:72.0354505169867x72

注意逻辑和物理DPI?该物理DPI看起来很熟悉吗?在阅读了有关72DPI反映1pt = 1px的文章后,这一切都是有道理的。在您的各种测试机上尝试此代码,让我知道它的发展! (仅供参考,我在C#Winforms应用程序(控制台应用程序)中运行了此代码 应该 能够获得屏幕设备上下文,但也许没有...)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top