1

Because of lack of Graphics object in certain places in my application, I decided to use TextRenderer class. What is quite surprising though is that it adds a lot of margins to measured text. For example:

private void button1_Click(object sender, EventArgs e) {

    using (var g = this.CreateGraphics()) {

        Font font = new Font("Calibri", 20.0f, GraphicsUnit.Pixel);
        Size size = TextRenderer.MeasureText("Ala ma kota", font);

        g.DrawRectangle(Pens.Red, new Rectangle(new Point(10, 10), size));
        TextRenderer.DrawText(g, "Ala ma kota", font, new Point(10, 10), Color.Black);
    }
}

Gives the following result:

Text with margins

Why does it do so? Is there a way to force it to get the real text size? (and of course draw it in the same rectangle it returns)

Spook
  • 25,318
  • 18
  • 90
  • 167
  • You can try to add in your code a TextFormatFlags Enumeration, as you can see [here](http://msdn.microsoft.com/en-us/library/system.windows.forms.textformatflags(v=vs.110).aspx) – Emi987 Apr 09 '14 at 07:50

1 Answers1

4

From MSDN:

For example, the default behavior of the TextRenderer is to add padding to the bounding rectangle of the drawn text to accommodate overhanging glyphs. If you need to draw a line of text without these extra spaces, use the versions of DrawText and MeasureText that take a Size and TextFormatFlags parameter, as shown in the example.

You must also pass the Graphics object for correct results, because:

This overload of MeasureText(String, Font, Size, TextFormatFlags) will ignore a TextFormatFlags value of NoPadding or LeftAndRightPadding. If you are specifying a padding value other than the default, you should use the overload of MeasureText(IDeviceContext, String, Font, Size, TextFormatFlags) that takes a IDeviceContext object.

Size size = TextRenderer.MeasureText(g,
                                     "Ala ma kota",
                                     font,
                                     new Size(int.MaxValue, int.MaxValue),
                                     TextFormatFlags.NoPadding);

TextRenderer.DrawText(g, "Ala ma kota", font,
                      new Point(10, 10),
                      Color.Black,
                      TextFormatFlags.NoPadding);

g.DrawRectangle(Pens.Red, new Rectangle(new Point(10, 10), size));

Also have a look at using the Graphics methods directly: GDI+ MeasureString() is incorrectly trimming text

Community
  • 1
  • 1
GSerg
  • 76,472
  • 17
  • 159
  • 346
  • +1, that removes the extra padding. But in the place where I do the measuring, I have no `Graphics` object :( – Spook Apr 09 '14 at 07:59
  • @Spook Unfortunately this won't work. I have edited in the notes from MSDN. You can however provide your own implementation of `IDeviceContext` that would return e.g. the screen `hDC`, this way you wouldn't need `Graphics`. – GSerg Apr 09 '14 at 08:04
  • Not good :( It seems I'll have to change architecture of my project, such that Graphics object will be available there... – Spook Apr 09 '14 at 08:10
  • @Spook Do you mean creating a graphics object is not allowed, or only that implementing a IDeviceContext would be too much? If the latter, this seems to work: using (var g = FromHwnd(IntPtr.Zero)){var size = MeasureText(g,s,f,Size.Empty, TextFormatFlags.NoPadding);} (Not sure if Intptr.Zero (screen) works on every machine, in the past, I've used a dummy static bitmap and created a Graphics object from that) – Me.Name Apr 09 '14 at 09:28
  • @Me.Name It might have worked, but there's a catch. Since (AFAIR) Windows 8, different windows may have different DPI settings - in such situation I might get invalid metrics if DPIs of window and desktop differs. – Spook Apr 09 '14 at 09:34