Центрирование отдельного персонажа с DrawString - PullRequest
5 голосов
/ 08 декабря 2011

Я испробовал все предложенные способы центрирования текста, но я не могу получить желаемые результаты при центрировании отдельного символа.

У меня есть прямоугольник.В этом прямоугольнике я рисую круг с помощью DrawEllipse.Теперь я хочу нарисовать один символ внутри круга, используя тот же прямоугольник и DrawString, чтобы он был идеально отцентрирован.

Вот мой основной код:

StringFormat stringFormat = new StringFormat();
stringFormat.Alignment = StringAlignment.Center;
stringFormat.LineAlignment = StringAlignment.Center;

using (Graphics g = Graphics.FromImage(xImage))
{
    g.SmoothingMode = SmoothingMode.AntiAlias;
    g.TextRenderingHint = TextRenderingHint.AntiAlias;
    g.CompositingQuality = CompositingQuality.HighQuality;
    g.InterpolationMode = InterpolationMode.HighQualityBicubic;
    g.PixelOffsetMode = PixelOffsetMode.HighQuality;

    g.FillEllipse(fillBrush, imageRect.X, imageRect.Y, imageRect.Width - 1, imageRect.Height - 1);

    g.DrawString(Text, font, Brushes.White, imageRect, stringFormat);
}

Текст центрирован горизонтально... но это не правильно центрировано по вертикали.Используя симметричный символ, такой как заглавная буква «I», я обнаружил, что верхняя часть символа всегда намного ближе к краю прямоугольника, чем нижняя часть символа.Расстояние, вероятно, составляет не менее 50%.

Я предполагаю, что оно измеряет достаточно места для символов, таких как строчная буква "j", которая висит ниже.Однако, поскольку я пытаюсь создать графический значок с одной буквой, я хочу более точное центрирование.

Ответы [ 3 ]

7 голосов
/ 08 декабря 2011

Используйте GraphicsPath для выполнения расчета размера.

public static void DrawCenteredText(Graphics canvas, Font font, float size, Rectangle bounds, string text)
{
    var path = new GraphicsPath();
    path.AddString(text, font.FontFamily, (int)font.Style, size, new Point(0, 0), StringFormat.GenericTypographic);

    // Determine physical size of the character when rendered
    var area = Rectangle.Round(path.GetBounds());

    // Slide it to be centered in the specified bounds
    var offset = new Point(bounds.Left + (bounds.Width / 2 - area.Width / 2) - area.Left, bounds.Top + (bounds.Height / 2 - area.Height / 2) - area.Top);
    var translate = new Matrix();
    translate.Translate(offset.X, offset.Y);
    path.Transform(translate);

    // Now render it however desired
    canvas.SmoothingMode = SmoothingMode.AntiAlias;
    canvas.FillPath(SystemBrushes.ControlText, path);
}
0 голосов
/ 06 марта 2014

Хотя ответ Джона Арлена идеален, я бы хотел опубликовать свой ответ:

    private void Form1_Paint(object sender, PaintEventArgs e)
    {
         // Set up string.
        string measureString = "HelloWorld";
        Font stringFont = new Font("Arial", 100, FontStyle.Regular, GraphicsUnit.Pixel);

        // Measure string.
        SizeF stringSize = new SizeF();
        stringSize = e.Graphics.MeasureString(measureString, stringFont);

        // Draw rectangle representing size of string.
        e.Graphics.DrawRectangle(new Pen(Color.Red, 1), 10.0F, 10.0F, stringSize.Width, stringSize.Height);

        // Draw string to screen.
        e.Graphics.DrawString(measureString, stringFont, Brushes.Black, new PointF(10, 10f + stringSize.Height / 12.0f));
    }

код результата так: result in my computer

«HelloWorld» центрируется вертикально в красном поле.

Для высоты линии спуска примерно равна 1/6 от stringSize.Height, рассчитанной по MeasureString


| верхняя обивка 1/6

| слово тела 3/6

| слово спускатель 1/6

| нижняя обивка 1/6

0 голосов
/ 08 декабря 2011

если вы используете

StringFormat stringFormat = new StringFormat(StringFormat.GenericTypographic);

вы получили

enter image description here

вместо

enter image description here

надеюсь, что этопомогает

...