Как реализовать AutoSize - PullRequest
1 голос
/ 20 мая 2010

Я пытаюсь найти хороший способ автоматического изменения размера Rectangle, в котором нарисован текст. Я в основном хочу, чтобы размер имел отношение ширины / высоты, а затем "увеличивался" в соответствии с этим соотношением, чтобы соответствовать тексту. Я посмотрел на Graphics.MeasureString, но я не думаю, что он делает то, что я ищу (возможно, он делает, и я просто использую это неправильно).

Я не хочу указывать конкретную ширину прямоугольника для рисования. Вместо этого я хочу сказать, найти наименьшую ширину / высоту, чтобы соответствовать этому тексту, учитывая минимальная ширина , но найденный прямоугольник должен иметь определенное соотношение ширины и высоты.

Это не должно быть специфично для C #, любая идея для решения этой проблемы, я уверен, может быть сопоставлена ​​с C #.

Спасибо!

Ответы [ 4 ]

1 голос
/ 20 мая 2010

Вы должны использовать TextRenderer.MeasureText, все элементы управления используют TextRenderer для рисования текста в .NET 2.0 и выше.

Не существует однозначного решения вашего вопроса, есть много возможных способов разместить текст в прямоугольнике. Широкая, отображающая только одну строку, так же действительна, как и узкая, отображающая много строк. Вам придется ограничить одно из измерений. Это реалистичное требование, этот прямоугольник отображается внутри какого-то другого элемента управления, и этот элемент управления имеет определенный ClientSize. Вам нужно решить, как вы хотите выложить это.

1 голос
/ 20 мая 2010

Полагаю, вы можете использовать Graphics.MeasureString . Это то, что я использовал в своем коде GUI для рисования прямоугольников вокруг текста. Вы передаете ему текст и шрифт, который хотите использовать, он возвращает вам прямоугольник (технически объект SizeF - ширина и высота). Затем вы можете отрегулировать этот прямоугольник в нужном вам соотношении:

Graphics g = CreateGraphics();
String s = "Hello, World!";
SizeF sizeF = g.MeasureString(s, new Font("Arial", 8));

// Now I have a rectangle to adjust.
float myRatio = 2F;
SizeF adjustedSizeF = new SizeF(sizeF.Width * myRatio, sizeF.Height * myRatio);
RectangleF rectangle = new RectangleF(new PointF(0, 0), adjustedSizeF);

Правильно ли я понимаю ваш вопрос?

0 голосов
/ 20 мая 2010

Я нашел свое собственное решение.Следующий код определяет наилучший прямоугольник (соответствующий соотношению) для размещения текста.Он использует разделяй и властвуй, чтобы найти ближайший прямоугольник (уменьшив ширину на некоторый «шаг»).Этот алгоритм использует минимальную ширину, которая всегда соблюдается, и я уверен, что это можно изменить, чтобы включить максимальную ширину.Мысли?

private Size GetPreferredSize(String text, Font font, StringFormat format)
{

    Graphics graphics = this.CreateGraphics();

    if (format == null)
    {
        format = new StringFormat();
    }

    SizeF textSize = SizeF.Empty;

    // The minimum width allowed for the rectangle.
    double minWidth = 100;

    // The ratio for the height compared to the width.
    double heightRatio = 0.61803399; // Gloden ratio to make it look pretty :)

    // The amount to in/decrement for width.
    double step = 100;

    // The new width to be set.
    double newWidth = minWidth;

    // Find the largest width that the text fits into.
    while (true)
    {
        textSize = graphics.MeasureString(text, font, (int)Math.Round(newWidth), format);

        if (textSize.Height <= newWidth * heightRatio)
        {
            break;
        }

        newWidth += step;
    }

    step /= 2;

    // Continuously divide the step to adjust the rectangle.
    while (true)
    {

        // Ensure step.
        if (step < 1)
        {
            break;
        }

        // Ensure minimum width.
        if (newWidth - step < minWidth)
        {
            break;
        }

        // Try to subract the step from the width.
        while (true)
        {

            // Measure the text.
            textSize = graphics.MeasureString(text, font, (int)Math.Round(newWidth - step), format);

            // If the text height is going to be less than the new height, decrease the new width.
            // Otherwise, break to the next lowest step.
            if (textSize.Height < (newWidth - step) * heightRatio)
            {
                newWidth -= step;
            }
            else
            {
                break;
            }

        }

        step /= 2;
    }

    double width = newWidth;
    double height = width * heightRatio;

    return new Size((int)Math.Ceiling(width), (int)Math.Ceiling(height));
}
0 голосов
/ 20 мая 2010

В конце моего комментария о System.Windows.Forms.Label, может быть, вы могли бы взглянуть на код, управляющий написанием этикетки? Если вы используете Reflector, это должно помочь вам.

Кажется, там есть некоторые методы, например, GetPreferredSizeCore (), которые, вероятно, имеют то, что вы хотите, и я уверен, что это может быть сделано достаточно общим, если немного поработать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...