1

In a WinForms app, I am trying to measure the size of some text I want to draw with no padding. Here's the closest I've gotten...

    protected override void OnPaint(PaintEventArgs e) {
        DrawIt(e.Graphics);
    }

    private void DrawIt(Graphics graphics) {
        var text = "123";
        var font = new Font("Arial", 32);
        var proposedSize = new Size(int.MaxValue, int.MaxValue);
        var measuredSize = TextRenderer.MeasureText(graphics, text, font, proposedSize, TextFormatFlags.NoPadding);
        var rect = new Rectangle(100, 100, measuredSize.Width, measuredSize.Height);
        graphics.DrawRectangle(Pens.Blue, rect);
        TextRenderer.DrawText(graphics, text, font, rect, Color.Black, TextFormatFlags.NoPadding);
    }

... but as you can see from the results ...

enter image description here

... there is still a considerable amount of padding, particularly on the top and bottom. Is there any way to measure the actual bounds of the drawn characters (with something really awful like printing to an image and then looking for painted pixels)?

Thanks in advance.

BoCoKeith
  • 817
  • 10
  • 21
  • The space is reserved for taller characters. – Reza Aghaei Jun 23 '18 at 16:56
  • 4
    You can get the bounds of a graphicspath containing the text. See [here](https://stackoverflow.com/questions/28893445/how-to-draw-a-given-character-in-exact-height/28901887?s=2|35.9473#28901887) for an example using that technique to achieve drawing at an exact height.. – TaW Jun 23 '18 at 16:56
  • Something to keep in mind, is that fonts have ascenders and descenders (ex., for instance the follow letters: dpM), the space above and below. – nocturns2 Jun 23 '18 at 17:22
  • I don't think that Graphics.MeasureString method measures the height of the typeface part of a specified font. I think it only measures the widths of the chars. Also, something about displaying at different resolutions can render differently. This link has more info: https://msdn.microsoft.com/en-us/library/6xe5hazb%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396 – nocturns2 Jun 23 '18 at 17:30
  • 1
    The closet thing to what you need is what is mentioned in the second comment. Add the string to a path, then get the bound of path. – Reza Aghaei Jun 23 '18 at 17:45

2 Answers2

3

(I've marked this answer as "the" answer just so people know it was answered, but @TaW actually provided the solution -- see his link above.)

@TaW - That was the trick. I'm still struggling to get the text to go where I want it to, but I'm over the hump. Here's the code I ended out with...

    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", 40);
        // 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.SizeInPoints, new Point(0, 0), StringFormat.GenericDefault);
        var bounds = path.GetBounds();
        // Move it where I want it.
        var xlate = new Matrix();
        xlate.Translate(100, 100);
        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);
    }

... and here is the result (notice the nice, tight bounding box) ...

enter image description here

BoCoKeith
  • 817
  • 10
  • 21
  • How about Vice Versa? The Text will be dependent on the Rectangle after the Rectangle depended it's size to the text? I've been trying to find how to resize the text so I'm asking this – HEWhoDoesn'tKnow Nov 06 '18 at 03:24
  • The issue here is that the font size returned from GraphicsPath.Bounds and Graphics.MeasureString is very different. Like 30 %. See here: https://github.com/dotnet/winforms/issues/7485 – user3625699 Jul 24 '22 at 16:03
0

Have you tried

Graphics.MeasureString("myString", myFont, int.MaxValue, StringFormat.GenericTypographic)

Michael
  • 1,931
  • 2
  • 8
  • 22