Различное масштабирование при отрисовке метафайла на разных машинах

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

Вот как приложение выглядит на настольном компьютере с Windows 7: введите здесь описание изображения

Вот как приложение выглядит на ноутбуке с Windows 8: введите здесь описание изображения

Исходный код:

private void MainForm_Paint(object sender, PaintEventArgs e)
{
   var g = e.Graphics;
   var blueBrush = new SolidBrush(Color.Blue);
   var bluePen = new Pen(blueBrush);
   g.DrawRectangle(bluePen, 0, 0, 200, 200);
   g.DrawLine(bluePen, 100, 0, 100, 200);
   g.DrawLine(bluePen, 0, 100, 200, 100);
   g.DrawString(g.DpiX+" dpi", new Font("Arial", 10), blueBrush, 0, 205);

   Metafile metafile;
   var size = new Size(200, 200);
   using (var stream = new MemoryStream())
   {
      using (Graphics offScreenBufferGraphics = Graphics.FromHwndInternal(IntPtr.Zero))
      {
         IntPtr deviceContextHandle = offScreenBufferGraphics.GetHdc();
         metafile = new Metafile(stream, deviceContextHandle, new RectangleF(0, 0, size.Width, size.Height), MetafileFrameUnit.Millimeter, EmfType.EmfPlusOnly);
         offScreenBufferGraphics.ReleaseHdc();

         using (Graphics mg = Graphics.FromImage(metafile))
         {
            mg.PageUnit = GraphicsUnit.Millimeter;

            var redPen = new Pen(new SolidBrush(Color.Red));
            const float scaleFactor = 0.75f;
            mg.ScaleTransform(scaleFactor, scaleFactor);
            mg.DrawLine(redPen, 0, 0, 200, 200);
            mg.DrawLine(redPen, 0, 200, 200, 0);
         }
      }
   }

   g.DrawImage(metafile, 0, 0, 200, 200);
}

Обе машины настроены на 96 точек на дюйм, но машина Win8 делает метафайл (красный крест) меньше.

Масштабный коэффициент 0,75 рассчитывается из разницы между стандартным разрешением 72 dpi и текущим 96 dpi, 72/96 = 0,75, правильно ли это? Изменить: см. ответ ниже, почему это не сработает.

Но в основном, почему он масштабируется по-разному на машине с Win8 и какие настройки я могу выбрать для компенсации? Похоже, машине с Win8 нужен коэффициент масштабирования около 1,25, чтобы красный крест совпадал с синим прямоугольником.

Спасибо!


person salle55    schedule 09.11.2014    source источник


Ответы (1)


Сам нашел ответ после прочтения этого кода статья проекта. Оказывается, размер экрана на компьютере (1920x1200 на рабочем столе и 1600x900 на ноутбуке) влияет на разрешение метафайла. Предположение о 72 точках на дюйм, которое использовалось для расчета коэффициента масштабирования 0,75, было несколько правильным на моем настольном компьютере, но не на ноутбуке с Win8.

Разрешение метафайла можно получить из заголовка метафайла, а затем использовать для вычисления правильного коэффициента масштабирования:

var metafileHeader = metafile.GetMetafileHeader();
float sx = metafileHeader.DpiX/g.DpiX;
float sy = metafileHeader.DpiY/g.DpiY;
mg.ScaleTransform(sx, sy);

Полный код можно найти здесь.

Затем я получаю правильное масштабирование на обеих машинах:

введите здесь описание изображения

person salle55    schedule 10.11.2014