c# – Unit of measurement of Method: String.Length

c# – Unit of measurement of Method: String.Length

The correct way to determine the width or the size of text, when displayed on-screen using Windows is to use Graphics.MeasureString:

Measures the specified string when drawn with the specified Font.

The reason for this is that the following things will impact the exact size you get back:

  • Obviously the text
  • The font family/type used
  • The font size used
  • Font styling (bold, italic, etc.)

Here is a very short example:

using (var f = new Font(Arial, 8.25f))
using (var g = Graphics.FromHwnd(IntPtr.Zero)) // Desktop
{
    SizeF size = g.MeasureString(Test, f);
}

Obviously you should use a Graphics object obtained from a control, and the font of the label (if youre going to use it for a label) to avoid constructing and using the objects above.

Well, the short answer to your question:

Is the problem that String.Length and Label.Width have different measure units?

Is yes.

See here for more information on the Width property, and here for more information on String.Length.

Basically: String.Length refers to the number of characters in the string. ABC123 would return 6. Control.Width is a measurement in pixels. And since different fonts appear differently, it would be extremely cumbersome to try and figure out N characters in X font is Y pixels. (EDIT: And thats assuming youre using a mono-width font. If not, its even more complex as iii is visibly longer than aaa.)

In regards to your follow-up:

Are there any other ways to handle this?

(EDIT: Changing this part after coming up with an idea in comments)

1) Write the string to an image file

2) Find a suitable library that can determine color from a coordinate or set of coordinates in an image

3) Loop N times over the rows of pixels your image where N = the height of the image

4) Look for lines containing black pixels. We dont want lines that are ALL white as that would just be the buffer above and below our text.

5) Iterate over each pixel in the current row and store the X coordinate of the first black pixel, then store the X coordinate of every black pixel after the first in a temporary variable

6) Store the difference between lastBlackPixel and firstBlackPixel in a variable

7) Compare the difference between those two points for every row in your image. If the current difference is greater than largestKnownDifference then update that variable with the new distance.

That should determine the width of the text. Or maybe iterate each column and store the position of the first black pixel and then the the position of the last column to contain a black pixel? I dont know, I havent had my coffee yet. Lots of ways to skin a cat.

c# – Unit of measurement of Method: String.Length

You could take a look into Labels autosize property. Setting this to true will make the label to adjust its width according to string size. However, this might not get the desired result for very long texts.

If you want to be able to put long texts and not obtain very long labels, you can wrap the text by also setting its MaximumSize.

[EDIT]
I think measuring can be done by getting the width after setting it autosized (a posteriori).

An alternative is to try to measure the text by using Graphics.MeasureString that uses the actual text and used font to provide the size. A fully working example can be found here (apriori).

Leave a Reply

Your email address will not be published. Required fields are marked *