Как вычислить правильную ширину цифры в пикселях?
У меня есть пользовательский элемент управления, который может иметь настраиваемый пользователем шрифт в будущем (масштабирование уже реализовано). Я должен заполнить прямоугольник двумя цифрами, которые образуют число base-10. У меня есть разные цвета для нуля, одной или обеих цифр.
Со шрифтом {имя = Microsoft Sans Serif
Размер = 16
} и следующее Graphics.MeasureString
вызовы метода:
g.MeasureString("00", Font);
g.MeasureString("0", Font);
Я получил:
- Размер "00" равен {Width =
31.5486088
Высота =26.8124962
} - Размер "0" равен {Width =
19.3298588
Высота =26.8124962
}
Ширина "0" намного больше, чем половина ширины "00".
Я знаю методы Graphics.MeasureString, у них много перегрузок, и я также знаю класс StringFormat. Как я могу правильно рассчитать ширину символа '0'?
Поскольку шрифт будет настраиваться пользователем, я не хочу решать проблему, используя моноширинный шрифт.
Если я использую следующие звонки:
g.MeasureString("00", Font, 999, StringFormat.GenericTypographic);
g.MeasureString("0", Font, 999, StringFormat.GenericTypographic);
Ширина "0" кажется равной половине ширины "00", но цифры перекрываются, когда рисуется с меньшим размером шрифта:
Обновление: в методе OnPaint UserControl у меня есть этот код:
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);
Шрифт {Name = "Microsoft Sans Serif" Size=25}
, При запуске программы это то, что видно:
Я хочу сделать цифры по центру синих прямоугольников. Прямоугольники должны быть настолько большими, насколько это возможно в UserControl, но также должны оставлять место для процента от высоты UserControl. Шрифт должен адаптироваться к прямоугольникам.
1 ответ
Небольшие корректировки необходимы, чтобы сделать эту работу, как предполагалось:
TextRenderingHint.ClearTypeGridFit
дает лучший результат при рендеринге текста.
Он более точный и хорошо работает с сеткойGraphics.DrawString
,
См. Примечания, которые вы можете найти в ответе, связанном ниже, для получения дополнительной информации по этому вопросу.StringFormat
выравнивание по горизонтали и вертикали.- Модифицированный метод, который позволяет рисовать строки любой длины.
Если строка больше контейнера, она будет перенесена с текущими настройками. - Ненужные:
Brush
а такжеPen
объявляются вне события Paint, чтобы разрешить их повторное определение при необходимости.
Разные реализации MeasureCharacterRanges
Вот:
Как выделить обернутый текст в элементе управления
Около Graphics.DrawString
а также TextRenderingHint.ClearTypeGridFit
:
Рисование длинной строки в растровом изображении приводит к проблемам с рисованием
Шрифт 48em:
Шрифт 16em:
Pen pen = new Pen(Color.LightGreen, 1);
Brush brush = new SolidBrush(Color.White);
string sourceDigits = "010011001";
private void panel1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
CharacterRange[] charRanges = new CharacterRange[sourceDigits.Length];
for (int chx = 0; chx < sourceDigits.Length; ++chx) {
charRanges[chx] = new CharacterRange(chx, 1);
}
using (StringFormat sf = new StringFormat())
{
sf.Alignment = StringAlignment.Center;
sf.LineAlignment = StringAlignment.Center;
sf.SetMeasurableCharacterRanges(charRanges);
Region[] regions = e.Graphics.MeasureCharacterRanges(sourceDigits, Font, e.ClipRectangle, sf);
for (int i = 0; i < regions.Length; i++) {
RectangleF rect = regions[i].GetBounds(e.Graphics);
e.Graphics.DrawRectangle(pen, rect.X, rect.Y, rect.Width, rect.Height);
e.Graphics.DrawString(char.ToString(sourceDigits[i]), Font, brush, rect, sf);
}
}
}