Вывод центра текста из Graphics.DrawString()
Я использую класс Graphics
.NETCF(Windows Mobile) и метод DrawString()
для отображения одного символа на экране.
Проблема в том, что я не могу правильно отцентрировать его. Независимо от того, что я установил для координаты Y местоположения рендеринга строки, она всегда получается меньше, и чем больше размер текста, тем больше смещение Y.
Например, при размере текста 12 смещение составляет около 4, а при 32 смещение составляет около 10.
Я хочу, чтобы персонаж занимал вертикально большую часть прямоугольника, в котором он нарисован, и центрировался горизонтально. Вот мой основной код. this
ссылка на пользовательский элемент управления, в котором он рисуется.
Graphics g = this.CreateGraphics();
float padx = ((float)this.Size.Width) * (0.05F);
float pady = ((float)this.Size.Height) * (0.05F);
float width = ((float)this.Size.Width) - 2 * padx;
float height = ((float)this.Size.Height) - 2 * pady;
float emSize = height;
g.DrawString(letter, new Font(FontFamily.GenericSansSerif, emSize, FontStyle.Regular),
new SolidBrush(Color.Black), padx, pady);
Да, я знаю, что есть элемент управления меткой, который я мог бы использовать вместо этого и установить для него центрирование, но на самом деле мне нужно сделать это вручную с помощью класса Graphics
.
Ответы
Ответ 1
Благодаря сочетанию предложений, которые я получил, я придумал следующее:
private void DrawLetter()
{
Graphics g = this.CreateGraphics();
float width = ((float)this.ClientRectangle.Width);
float height = ((float)this.ClientRectangle.Width);
float emSize = height;
Font font = new Font(FontFamily.GenericSansSerif, emSize, FontStyle.Regular);
font = FindBestFitFont(g, letter.ToString(), font, this.ClientRectangle.Size);
SizeF size = g.MeasureString(letter.ToString(), font);
g.DrawString(letter, font, new SolidBrush(Color.Black), (width-size.Width)/2, 0);
}
private Font FindBestFitFont(Graphics g, String text, Font font, Size proposedSize)
{
// Compute actual size, shrink if needed
while (true)
{
SizeF size = g.MeasureString(text, font);
// It fits, back out
if (size.Height <= proposedSize.Height &&
size.Width <= proposedSize.Width) { return font; }
// Try a smaller font (90% of old size)
Font oldFont = font;
font = new Font(font.Name, (float)(font.Size * .9), font.Style);
oldFont.Dispose();
}
}
Пока это работает безупречно.
Единственное, что я бы изменил, - это переместить вызов FindBestFitFont() в событие OnResize(), чтобы я не вызывал его каждый раз, когда я рисую письмо. Его нужно вызывать только при изменении размера элемента управления. Я просто включил его в функцию для полноты.
Ответ 2
Я хочу добавить еще одно голосование для объекта StringFormat.
Вы можете использовать это просто, чтобы указать "центр, центр", и текст будет нанесен централизованно в прямоугольник или предоставленные точки:
StringFormat format = new StringFormat();
format.LineAlignment = StringAlignment.Center;
format.Alignment = StringAlignment.Center;
Однако в CF есть одна проблема. Если вы используете Center для обоих значений, он отключает функцию TextWrapping. Не знаю, почему это происходит, кажется, это ошибка с CF.
Ответ 3
Чтобы выровнять текст, используйте следующее:
StringFormat sf = new StringFormat();
sf.LineAlignment = StringAlignment.Center;
sf.Alignment = StringAlignment.Center;
e.Graphics.DrawString("My String", this.Font, Brushes.Black, ClientRectangle, sf);
Обратите внимание, что текст здесь выровнен по заданным границам. В этом примере это ClientRectangle.
Ответ 4
Чтобы нарисовать центрированный текст:
TextRenderer.DrawText(g, "my text", Font, Bounds, ForeColor, BackColor,
TextFormatFlags.HorizontalCenter |
TextFormatFlags.VerticalCenter |
TextFormatFlags.GlyphOverhangPadding);
Определение оптимального размера шрифта для заполнения области немного сложнее. Одна работающая душа, которую я обнаружил, - пробная ошибка: начните с большого шрифта, затем многократно измеряйте строку и уменьшайте шрифт до тех пор, пока он не подходит.
Font FindBestFitFont(Graphics g, String text, Font font,
Size proposedSize, TextFormatFlags flags)
{
// Compute actual size, shrink if needed
while (true)
{
Size size = TextRenderer.MeasureText(g, text, font, proposedSize, flags);
// It fits, back out
if ( size.Height <= proposedSize.Height &&
size.Width <= proposedSize.Width) { return font; }
// Try a smaller font (90% of old size)
Font oldFont = font;
font = new Font(font.FontFamily, (float)(font.Size * .9));
oldFont.Dispose();
}
}
Вы использовали бы это как:
Font bestFitFont = FindBestFitFont(g, text, someBigFont, sizeToFitIn, flags);
// Then do your drawing using the bestFitFont
// Don't forget to dispose the font (if/when needed)
Ответ 5
Вы можете использовать экземпляр объекта StringFormat
, переданного в метод DrawString
, чтобы центрировать текст.
Смотрите Graphics.DrawString Method и Класс StringFormat.
Ответ 6
Вот какой код. Предполагается, что вы делаете это в форме или в UserControl.
Graphics g = this.CreateGraphics();
SizeF size = g.MeasureString("string to measure");
int nLeft = Convert.ToInt32((this.ClientRectangle.Width / 2) - (size.Width / 2));
int nTop = Convert.ToInt32((this.ClientRectangle.Height / 2) - (size.Height / 2));
Из вашего сообщения это звучит так, как часть ClientRectangle (как, в которой вы ее не используете) - это то, что вам трудно.