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

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

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

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

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

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

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

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

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

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

1 Ответ

4 голосов
/ 05 декабря 2011

Моя гипотеза

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

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

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

Как проверитьМоя гипотеза

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

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

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

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

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

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

Также во время поиска в Windows 7 я обнаружил ссылку «Установить произвольный размер текста (DPI)»в панели управления-> дисплей, который включает опцию «Использовать масштабирование DPI в стиле Windows 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 мм X 381 мм
  • Разрешение рабочего стола: 1920x1080
  • Логический DPI: 96x96
  • Физический DPI: 72.0354505169867x72

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

...