Рендеринг текста в WPF, чтобы он идеально вписался в данный прямоугольник - PullRequest
5 голосов
/ 21 января 2011

Мне нужно отобразить слова на холсте WPF таким образом, чтобы они идеально помещались в предварительно определенные поля.

Как правило, один блок содержит одну строку текста, от одной буквы до нескольких слов.

Текст внутри поля должен быть как можно большего размера, т. Е. Касаться всех границ поля (за исключением, возможно, там, где это может привести к слишком сильному искажению текста из-за ненормального соотношения полей и высоты).

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

Первое решение, в котором нельзя изменить исходное соотношение ширины / высоты текста,уже очень приятно!

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

Ответы [ 3 ]

5 голосов
/ 25 января 2011

Как сказал Робери Леви, вы можете использовать Viewbox для достижения этой цели.Однако сам текст не растянется, поэтому у вас все равно будет некоторое «поле» с нуля или более сторон в зависимости от вашего текста (как вы заметили).Чтобы обойти это, вы можете создать пользовательский элемент управления, который создает Geometry из FormattedText, а затем рисовать его с DrawGeometry в OnRender.Вы заметите, как качество текста улучшается с увеличением FontSize.Очень маленький текст (например, FontSize="10") не будет выглядеть очень резким в большом Viewbox, поэтому вам придется немного поэкспериментировать

enter image description here

Некоторыепример Xaml

<Canvas Background="Black">
    <Viewbox Canvas.Left="10" Canvas.Top="10"
             Stretch="Fill" Width="200" Height="50">
        <Border Background="Red">
            <local:StretchText Text="Text" Foreground="Green" FontSize="100"/>
        </Border>
    </Viewbox>
    <Viewbox Canvas.Left="230" Canvas.Top="10"
             Stretch="Fill" Width="200" Height="50">
        <Border Background="Red">
            <local:StretchText Text="B" Foreground="Green" FontSize="500"/>
        </Border>
    </Viewbox>
</Canvas>

StretchText.cs

public class StretchText : Control
{
    protected override void OnRender(DrawingContext drawingContext)
    {
        FormattedText formattedText = new FormattedText(
            Text,
            CultureInfo.GetCultureInfo("en-us"),
            FlowDirection.LeftToRight,
            new Typeface(FontFamily, FontStyle, FontWeight, FontStretches.Normal),
            FontSize,
            Foreground);

        Geometry textGeometry = formattedText.BuildGeometry(new Point(0, 0));
        this.MinWidth = textGeometry.Bounds.Width;
        this.MinHeight = textGeometry.Bounds.Height;

        TranslateTransform translateTransform = new TranslateTransform();
        translateTransform.X = -textGeometry.Bounds.Left;
        translateTransform.Y = -textGeometry.Bounds.Top;
        drawingContext.PushTransform(translateTransform);
        drawingContext.DrawGeometry(Foreground, new Pen(Foreground, 1.0), textGeometry);
    }

    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }
    public static readonly DependencyProperty TextProperty =
        DependencyProperty.Register("Text",
        typeof(string),
        typeof(StretchText),
        new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.AffectsRender));
}
4 голосов
/ 21 января 2011

Поместите TextBlock внутри Viewbox: http://msdn.microsoft.com/en-us/library/system.windows.controls.viewbox.aspx

0 голосов
/ 21 января 2011

Вы можете ознакомиться со статьей Чарльза Петцольда " Визуализация текста на пути с помощью WPF ". К сожалению, я не могу обновить свои знания о предмете в настоящее время из-за того, что что-то не так с сайтом MSDN, но он описал, как масштабировать текст в пути.

...