Как Excel вычисляет разрешение метафилей, которые он генерирует при копировании диапазона «как показано на экране»?

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

  •  25-10-2019
  •  | 
  •  

Вопрос

У меня есть код C#, который я получил http://bytes.com/topic/c-sharp/answers/572657-net-clipboard-metafiles который копирует диапазон ячеек под следующими двумя настройками:

  • Как показано на экране,
  • Как показано при печати.

Когда я смотрю на результирующее разрешение метафиле (которое задокументировано как Gets the resolution, in pixels-per-inch, of this Image object), Я получаю разные значения в зависимости от метода копирования.

  • С Как показано при печати Вариант, разрешение составляет 600, что, я полагаю, соответствует настройкам DPI, которые у меня есть в Excel.

  • С Как показано на экране настройка, он выплевывает что -то вроде Metafile.VerticalResolution = 72.08107 а также Metafile.HorizontalResolution = 71.95952. Анкет На других машинах я видел, как это значение сильно различалось (значения около 111, 130 и т. Д.).

Уровень увеличения, кажется, не влияет на это. Из того, что я наблюдал, значения остаются последовательными на одной машине, но могут отличаться от машины к машине.

Может ли кто -нибудь объяснить логику Excel следует при вычислении разрешения метафила в Как показано на экране Режим?

После изменения разрешения Windows и измерения разрешений метафильных, вот таблица, которую я сгенерировал (надеюсь, она выглядит правильно):

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
Это было полезно?

Решение

Моя гипотеза

Я полагаю, что это связано с запуском неродного разрешения на ЖК-мониторе. В «Старые времена» у CRTS не было местного разрешения как такового. Таким образом, компьютер не знал о каком -либо предпочтительном разрешении для данного размера монитора или соотношения сторон. С новыми цифровыми дисплеями (ЖК -дисплеев) компьютер теперь знает о предпочтительном разрешении и соотношении сторон для вашего дисплея при правильном установке. Моя машина Windows 7 показывает «рекомендованное» рядом с нативным разрешением моего ЖК -дисплея, а затем показывает 2 других разрешений равных соотношений сторон в черном, с оставшимися «несоответствиями», которые я не смягчался, но выбирается (что привело к складыванию или растянутым взглядам, которые я ненавижу видеть На других компьютерах народа!).

DPI по умолчанию 96 и 120 в окнах были установлены в дни ЭЛТ. Моя машина Windows 7 даже больше не говорит DPI, она просто говорит «меньше», «средний», «больше».

В любом случае, когда вы покупаете ЖК -монитор, который, скажем, 1920x1080 или 1920x1200, но устанавливает разрешение дисплея на что -то меньшее, вы приводите коэффициент преобразования. В случае не совпадающих горизонтальных и вертикальных разрешений, близких к 72, ваше неконосное разрешение дисплея может быть не точно таким же фактором масштабирования вертикально, поскольку горизонтально приводит к этому небольшому расхождению.

Как проверить мою гипотезу

На каждом из ваших тестовых машин записывают операционные системы, настроенные настройку и дисплей, нативное разрешение. Посмотрите, находится ли соотношение между этими двумя, близко к соотношению между вашим метафилем, как на экране «против 96 или 120 дюймов». Я бы предпочел, чтобы вы провели этот тест на физических машинах, чтобы просто исключить возможность дальнейшего масштабирования с помощью удаленного рабочего стола или драйверов виртуальных машин.

Если решение не сразу очевидно, сделайте еще один шаг и запишите настройки эксплуатации и панели управления для DPI или «меньшего», «среднего» и «большего». Windows XP может вести себя иначе, чем Windows Vista/Windows 7.

Вы также можете перезапустить тест на одной и той же физической машине несколько раз, настраивая настроенное разрешение дисплея между тестами и наблюдать за любыми изменениями. Если моя гипотеза верна, вы должны увидеть другое разрешение метафильного для каждого настроенного разрешения дисплея в одной и той же комбинации физической машины/дисплея, и этот результат должен быть предсказуемым и повторяемым (возвращение к первому разрешению должно вернуться к тому же разрешению метафильного))

РЕДАКТИРОВАТЬ #1

Я нашел отличную статью, которая обсуждает физический DPI против логического DPI. Прочитать об этом: Откуда 96 DPI в Windows?

Так что теперь следующий тест, который бы я рекомендовал, - это изменение дисплеев! У вас есть другой ЖК -монитор бренда/размера/разрешения, доступный для тестирования? Вам не нужно столько линий, сколько ваш первый тест выше, так как мы установили, что различные разрешения, как правило, производят очень похожий DPI для одного и того же дисплея. Просто проверьте, возможно, пару общих решений, включая нативное разрешение дисплея и 1024x768 как «базовый уровень» для сравнения.

Кроме того, когда я толкал в Windows 7, я нашел ссылку «Установить пользовательский размер текста (DPI)» в панели управления-> дисплей, который включал в себя опцию «Использовать масштабирование DPI в стиле XP». Хотя я не думаю, что это главная проблема, любопытство заставляет меня интересоваться его эффектом, поэтому я подумал, что упомяну об этом.

РЕДАКТИРОВАТЬ #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 мм х 381 мм
  • Рабочее разрешение: 1920x1080
  • Логический DPI: 96x96
  • Физический DPI: 72.0354505169867X72

Обратите внимание на логический и физический DPI? Этот физический DPI выглядит знакомым? Все это имеет смысл после прочтения этой статьи о 72DPI, отражающем 1pt = 1px. Попробуйте этот код на различных тестовых машинах и дайте мне знать, как это происходит! (К вашему сведению, я запустил этот код в приложении C# Winforms, приложении консоли должен иметь возможность получить контекст устройства экрана, но, возможно, нет ...)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top