Alex Rivera | Logout

How to get the exact text margins used by TextRenderer

Asked 2010-12-13T11:26:35.167
30

System.Windows.Forms.TextRenderer.DrawText method renders formatted text with or without left and right padding depending on the value of the flags parameter:

  • TextFormatFlags.NoPadding - fits the text tightly into the bounding box,
  • TextFormatFlags.GlyphOverhangPadding - adds some left and right margins,
  • TextFormatFlags.LeftAndRightPadding - adds even bigger margins.

Now, my question is how can I get the exact amount of padding (left and right) added by DrawText to the text for a given device context, string, font etc?

I've dug into .NET 4 with .NET Reflector and found that TextRenderer calculates "overhang padding" which is 1/6 of the font's height and then multiplies this value to calculate left and right margins using these coefficients:

  • left 1.0, right 1.5 for TextFormatFlags.GlyphOverhangPadding,
  • left 2.0, right 2.5 for TextFormatFlags.LeftAndRightPadding.

The resulting values are rounded up and passed to the DrawTextExA or DrawTextExW native API functions. It's difficult to recreate this process because font's height is taken not from System.Drawing.Font but from System.Windows.Forms.Internal.WindowsFont and these classes return different values for the same font. And a lot of other internal BCL classes from the System.Windows.Forms.Internal namespace are involved. Decompiling all of them and reusing their code in my app is not an option, because that would be a serious .NET implementation dependency. That's why I need to know if there is some public API in WinForms or at least which Windows functions I can use to get the values of left and right margins.


Note: I've tried to TextRenderer.MeasureText with and without padding and compare the r

Edit
Report

1 Answer

1

I've done something similar a few years ago, to highlight search results (search pattern appears in bold etc.). My implementation was in DevExpress, so the code might not be relevant. If you think it's of use I can copy it, just need to find that implementation.

In System.Windows.Forms, the class to use would be Graphics. It has a MeasureCharacterRanges() method which accepts a StringFormat (start with GenericTypographic and go from there). It is much more appropriate than TextRenderer for displaying a complete string by chaining parts with different styles, fonts or brushes.

You've gone way further than me with the actual padding measuring. DevExpress's controls gave you the text bounding rectangle to start with so that was done for me.

Here's an article by Pierre Arnaud that came up for me in Google, which touches on this area. Unfortunately the GDI+ "Gory details" link there is broken.

Cheers,
Jonno

answered 2011-08-19T16:24:32.943

Your Answer