I have a custom control that may have user customizable Font in future (the zoom is already implemented). I must fill a rectangle under two digits that form a base-10 number. I have different colors for zero, one or both of the digits.
With the font {Name = Microsoft Sans Serif
Size=16
} and the following Graphics.MeasureString
method calls:
g.MeasureString("00", Font);
g.MeasureString("0", Font);
I get:
- The size of "00" is {Width =
31.5486088
Height =26.8124962
} - The size of "0" is {Width =
19.3298588
Height =26.8124962
}
The width of "0" is a lot bigger that half of the width of "00".
I know of the methods Graphics.MeasureString, it has many overloads, and I also know of the StringFormat class. How can I correctly compute the width of the '0' char?
Because the font will be user-customizable, I do not want to solve the problem using a monospace font.
If I use the following calls:
g.MeasureString("00", Font, 999, StringFormat.GenericTypographic);
g.MeasureString("0", Font, 999, StringFormat.GenericTypographic);
The width of "0" seems to be half of the width of "00", but the digits overlap when drawn with a smaller font size:
Update: In the OnPaint method of an UserControl I have this code:
Graphics g = e.Graphics;
int[] indices = { 0, 1 };
CharacterRange[] charRanges = new CharacterRange[indices.Length];
for (int chx = 0; chx < indices.Length; ++chx)
{
charRanges[chx] = new CharacterRange(indices[chx], 1);
}
StringFormat sf = new StringFormat(StringFormat.GenericDefault);
sf.SetMeasurableCharacterRanges(charRanges);
Region[] regions = e.Graphics.MeasureCharacterRanges("01", Font, e.ClipRectangle, sf);
RectangleF[] r = new RectangleF[regions.Length];
int i = 0;
foreach (Region rr in regions)
{
r[i] = rr.GetBounds(g);
g.DrawRectangle(Pens.Blue, r[i].X, r[i].Y, r[i].Width, r[i].Height);
++i;
}
g.DrawString("0", Font, Brushes.Black, r[0], sf);
g.DrawString("1", Font, Brushes.Black, r[1], sf);
The font is {Name = "Microsoft Sans Serif" Size=25}
. When running the program, this is what is visible:
I want to make the digits centered in the blue rectangles. The rectangles must be as big as possible in the UserControl but also leaving space for a percent of the Height of the UserControl. The Font should adapt to the rectangles.
Small adjustments are required to make this work as intended:
TextRenderingHint.ClearTypeGridFit
gives a better result when rendering the Text.It's more precise and works well with the grid-fitting nature of
Graphics.DrawString
.See the notes you can find in the answer linked below for more informations on this matter.
StringFormat
alignment in both horizontal and vertical dimensions.If the string is larger than the container, it will be wrapped, with the current settings.
Brush
andPen
are declared outside the Paint event, to allow their re-definition when required.Different implementations of
MeasureCharacterRanges
here:How to highlight wrapped text in a control
About
Graphics.DrawString
andTextRenderingHint.ClearTypeGridFit
:Drawing a Long String on to a Bitmap results in Drawing Issues
Font 48em:

Font 16em:

Font 9em:
