gpt4 book ai didi

c# - WPF TextFormatter 中第二行的缩进

转载 作者:太空狗 更新时间:2023-10-29 19:40:31 24 4
gpt4 key购买 nike

我正在使用 TextFormatter 制作 WPF 文本编辑器。我需要缩进每一段的第二行。

第二行的缩进宽度应与第一行第一个单词的宽度相同,包括第一个单词后的空格。类似的东西:

Indent of second line in Indentation Inde
second line in Indentation Indenta
of second line in Indentation of second l
ine in Indentation of second line in Inde
ntation of second line in

第二件事:段落中的最后一行应该在中间。

如何做到这一点?

提前致谢!

最佳答案

这绝非易事。我建议你使用 WPF 的 Advanced Text Formatting .

官方有一个(比较差,但也是唯一一个)样本:TextFormatting .

因此,我创建了一个带有文本框和特殊自定义控件的小型示例应用程序,该控件可以按您想要的方式同时呈现文本框中的文本(好吧,差不多了,请参阅最后的备注)。

<Window x:Class="WpfApp3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApp1"
Title="MainWindow" Height="550" Width="725">
<StackPanel Margin="10">
<TextBox Name="TbSource" AcceptsReturn="True" TextWrapping="Wrap" BorderThickness="1"
VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto"></TextBox>
<Border BorderThickness="1" BorderBrush="#ABADB3" Margin="0" Padding="0">
<local:MyTextControl Margin="5" Text="{Binding ElementName=TbSource, Path=Text}" />
</Border>
</StackPanel>
</Window>

我选择编写自定义控件,但您也可以构建几何图形(如官方“TextFormatting”示例)。

[ContentProperty(nameof(Text))]
public class MyTextControl : FrameworkElement
{
// I have only declared Text as a dependency property, but fonts, etc should be here
public static DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(MyTextControl),
new FrameworkPropertyMetadata(string.Empty,
FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsMeasure));

private List<TextLine> _lines = new List<TextLine>();
private TextFormatter _formatter = TextFormatter.Create();

public string Text { get => ((string)GetValue(TextProperty)); set { SetValue(TextProperty, value); } }

protected override Size MeasureOverride(Size availableSize)
{
// dispose old stuff
_lines.ForEach(l => l.Dispose());

_lines.Clear();
double height = 0;
double width = 0;
var ts = new MyTextSource(Text);
var index = 0;
double maxWidth = availableSize.Width;
if (double.IsInfinity(maxWidth))
{
// it means width was not fixed by any constraint above this.
// we pick an arbitrary value, we could use visual parent, etc.
maxWidth = 100;
}

double firstWordWidth = 0; // will be computed with the 1st line

while (index < Text.Length)
{
// we indent the second line
var props = new MyTextParagraphProperties(new MyTextRunProperties(), _lines.Count == 1 ? firstWordWidth : 0);
var line = _formatter.FormatLine(ts, index, maxWidth, props, null);
if (_lines.Count == 0)
{
// get first word and whitespace real width (so we can support justification / whitespaces widening, kerning)
firstWordWidth = line.GetDistanceFromCharacterHit(new CharacterHit(ts.FirstWordAndSpaces.Length, 0));
}

index += line.Length;
_lines.Add(line);

height += line.TextHeight;
width = Math.Max(width, line.WidthIncludingTrailingWhitespace);
}
return new Size(width, height);
}

protected override void OnRender(DrawingContext dc)
{
double height = 0;
for (int i = 0; i < _lines.Count; i++)
{
if (i == _lines.Count - 1)
{
// last line centered (using pixels, not characters)
_lines[i].Draw(dc, new Point((RenderSize.Width - _lines[i].Width) / 2, height), InvertAxes.None);
}
else
{
_lines[i].Draw(dc, new Point(0, height), InvertAxes.None);
}
height += _lines[i].TextHeight;
}
}
}

// this is a simple text source, it just gives back one set of characters for the whole string
public class MyTextSource : TextSource
{
public MyTextSource(string text)
{
Text = text;
}

public string Text { get; }

public string FirstWordAndSpaces
{
get
{
if (Text == null)
return null;

int pos = Text.IndexOf(' ');
if (pos < 0)
return Text;

while (pos < Text.Length && Text[pos] == ' ')
{
pos++;
}

return Text.Substring(0, pos);
}
}

public override TextRun GetTextRun(int index)
{
if (Text == null || index >= Text.Length)
return new TextEndOfParagraph(1);

return new TextCharacters(
Text,
index,
Text.Length - index,
new MyTextRunProperties());
}

public override TextSpan<CultureSpecificCharacterBufferRange> GetPrecedingText(int indexLimit) => throw new NotImplementedException();
public override int GetTextEffectCharacterIndexFromTextSourceCharacterIndex(int index) => throw new NotImplementedException();
}

public class MyTextParagraphProperties : TextParagraphProperties
{
public MyTextParagraphProperties(TextRunProperties defaultTextRunProperties, double indent)
{
DefaultTextRunProperties = defaultTextRunProperties;
Indent = indent;
}

// TODO: some of these should be DependencyProperties on the control
public override FlowDirection FlowDirection => FlowDirection.LeftToRight;
public override TextAlignment TextAlignment => TextAlignment.Justify;
public override double LineHeight => 0;
public override bool FirstLineInParagraph => true;
public override TextRunProperties DefaultTextRunProperties { get; }
public override TextWrapping TextWrapping => TextWrapping.Wrap;
public override TextMarkerProperties TextMarkerProperties => null;
public override double Indent { get; }
}

public class MyTextRunProperties : TextRunProperties
{
// TODO: some of these should be DependencyProperties on the control
public override Typeface Typeface => new Typeface("Segoe UI");
public override double FontRenderingEmSize => 20;
public override Brush ForegroundBrush => Brushes.Black;
public override Brush BackgroundBrush => Brushes.White;
public override double FontHintingEmSize => FontRenderingEmSize;
public override TextDecorationCollection TextDecorations => new TextDecorationCollection();
public override CultureInfo CultureInfo => CultureInfo.CurrentCulture;
public override TextEffectCollection TextEffects => new TextEffectCollection();
}

这是结果:

enter image description here

我没做过的事情:

  • 这不支持编辑,它不是文本框。对于这么小的赏金来说,这是太多的工作:-)
  • 支持多个段落。我刚刚缩进了示例中的第二行。您需要解析文本以提取您认为的“段落”。
  • 应添加 DPI 感知支持(适用于 .NET Framework 4.6.2 或更高版本)。这是在“TextFormatting”示例中完成的,您基本上需要随身携带 PixelsPerDip 值。
  • 在某些边缘情况下会发生什么(只有两行等)
  • 在自定义控件上公开常用属性(FontFamily 等...)

关于c# - WPF TextFormatter 中第二行的缩进,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46215326/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com