Альтернатива графике.ScaleTransform

#c# #graphics #gdi #scaletransform

#c# #графика #gdi #scaletransform

Вопрос:

Я делаю пользовательский чертеж с использованием GDI .

Обычно, если я хочу подогнать все, что я рисую, к окну, я вычисляю соответствующее соотношение и масштабирую все по этому соотношению:

 e.Graphics.ScaleTransform(ratio, ratio);
  

Проблема с ScaleTransform заключается в том, что она масштабирует все, включая штрихи пера и кисти.

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

Ответ №1:

Попробуйте сначала поместить все ваши объекты в GraphicsPath экземпляр. У него нет ScaleTransform метода, с помощью которого вы можете преобразовать объекты GraphicsPath.Transform . Вы можете передать масштабирующую матрицу через Matrix.Scale .

Комментарии:

1. Похоже, это может сработать, однако GraphicsPath не может рисовать изображение, а изображения — одна из главных вещей, которые я не хочу масштабировать.

Ответ №2:

Вы можете обернуть графический объект GDI и сохранить масштабный коэффициент

 interface IDrawing
{
   void Scale(float sx, float sy);
   void Translate(float dx, float dy);
   void SetPen(Color col, float thickness);
   void DrawLine(Point from, Point to);
   // ... more methods
}

class GdiPlusDrawing : IDrawing
{
   private float scale;
   private Graphics graphics;
   private Pen pen;

   public GdiPlusDrawing(Graphics g)
   {
      float scale = 1.0f;
   }

   public void Scale(float s)
   {
       scale *= s;
       graphics.ScaleTransform(s,s);
   }

   public void SetPen(Color color, float thickness)
   {
       // Use scale to compensate pen thickness.
       float penThickness = thickness/scale;
       pen = new Pen(color, penThickness);   // Note, need to dispose.
   }

   // Implement rest of IDrawing
}
  

Комментарии:

1. Обратите внимание, что если вы хотите избежать масштабирования только потому, что вам нужны тонкие (1 пиксель) линии, вы можете рисовать толщиной -1, чтобы принудительно создать линию в один пиксель независимо от масштаба.

Ответ №3:

Я думаю ScaleTransform , что работает с каждым числовым значением, с которым связан контекст GDI, поэтому, к сожалению, вы не можете просто использовать его для координат. У WPF есть GeometryTransform , но я не знаю его эквивалента в GDI .

Если вас беспокоит дублирование кода, вы всегда можете написать служебный метод для рисования фигур с определенным уровнем масштаба, применяемым к их точкам.

Вы также можете попробовать вручную изменить значение ScaleTransform , применив обратное значение к любым объектам, которые вы не хотите масштабировать; Я знаю, что некоторые кисти используют этот метод.

Ответ №4:

К счастью, в Pen есть локальная ScaleTransform, с помощью которой можно выполнить обратное масштабирование, чтобы компенсировать глобальное преобразование. Pen.ResetTransform после использования каждого масштабирования перед следующим или текущим масштабированием пера (независимо от контекста графики) может уменьшиться почти до нуля (фактически, до одного пикселя), выстрелить на луну или указать на полпути.