WinForms: Measure Text With No Padding

2019-08-15 20:57发布

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.

2条回答
Melony?
2楼-- · 2019-08-15 21:33

(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

查看更多
劫难
3楼-- · 2019-08-15 21:50

Have you tried

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

查看更多
登录 后发表回答