Question

I am doing custom drawing using the GDI+.

Normally if I want to fit whatever I am drawing to the window, I calculate the appropriate ratio and I ScaleTransform everything by that ratio:

e.Graphics.ScaleTransform(ratio, ratio);

The problem with ScaleTransform is that it scales everything including pen strokes and brushes.

Hoe do I scale all of the pixel coordinates of what I'm drawing? Every line, rectangle, or path is basically a series of points. So I can multiply all of those points by the ratio manually, but is there an easy alternative to do this more seamlessly?

Was it helpful?

Solution

You can wrap the GDI graphics object and store the scale factor

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
}

OTHER TIPS

Try putting all your objects in a GraphicsPath instance first. It doesn't have a ScaleTransform method but you can transform the objects with GraphicsPath.Transform. You can pass a scaling matrix via Matrix.Scale.

I think ScaleTransform works on every numeric value that the GDI context is concerned with, so you can't just use it for coordinates, unfortunately. WPF has a GeometryTransform but I don't know of an equivalent to it in GDI+.

If you're concerned about code duplication you could always write a utility method to draw the shapes with a certain scale level applied to their points.

You could also try manually reversing the ScaleTransform by applying the inverse of it to any objects you don't want scaled; I know some brushes expose this method.

Fortunately, Pen has a local ScaleTransform by which inverse rescaling can be done to compensate for the global transform. Pen.ResetTransform after using each rescaling before the next, or the current pen scaling (independent of graphics context) can shrink to nearly nothing (actually, one pixel), shoot to the moon, or points midway.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top