Search code examples
c#.netwinformsgraphicspath

WinForms: Drawing A Path In The Right Place


This is a follow-on to a question I asked here: WinForms: Measure Text With No Padding. The question is, given this code ...

    protected override void OnPaint(PaintEventArgs e) {
        e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
        DrawIt(e.Graphics);
    }

    private void DrawIt(Graphics graphics) {
        var text = "123";
        var font = new Font("Arial", 72);
        // Build a path containing the text in the desired font, and get its bounds.
        GraphicsPath path = new GraphicsPath();
        path.AddString(text, font.FontFamily, (int)font.Style, font.Size, new Point(0, 0), StringFormat.GenericDefault);
        var bounds = path.GetBounds();
        // Find center of the form.
        var cx = this.ClientRectangle.Left + this.ClientRectangle.Width / 2;
        var cy = this.ClientRectangle.Top + this.ClientRectangle.Height / 2;
        // Move it where I want it.
        var xlate = new Matrix();
        xlate.Translate(cx - bounds.Width / 2, cy - bounds.Height / 2);
        path.Transform(xlate);
        // Draw the path (and a bounding rectangle).
        graphics.DrawPath(Pens.Black, path);
        bounds = path.GetBounds();
        graphics.DrawRectangle(Pens.Blue, bounds.Left, bounds.Top, bounds.Width, bounds.Height);
        // This rectangle doesn't use the positioning from Translate but does use the same size.
        graphics.DrawRectangle(Pens.Red, cx - bounds.Width / 2, cy - bounds.Height / 2, bounds.Width, bounds.Height);
    }

... why don't the rectangles overlap?

enter image description here

Clearly, when I'm translating the path, I'm not translating by the same units that I'm later drawing them in, but I'm at a loss how to fix it. Any ideas?


Solution

  • You have a wrong assumption about Bounds of the path. Since you added the string to the path, starting from point (0,0), you are assuming the location of the bounds of the path is (0,0). That's not correct.

    The following illustration shows the relation between the origin that you added string, (0,0) and bounds of the path, blue rectangle:

    enter image description here

    To fix it, after adding the string and getting its bounds, store the location of the bounds:

    var p = bounds.Location;
    

    And then after applying the transformations, draw the rectangle this way:

    graphics.DrawRectangle(Pens.Red, 
         p.X + cx - bounds.Width / 2, p.Y + cy - bounds.Height / 2, 
         bounds.Width, bounds.Height);