WPF C# получить размер и положение встроенного элемента TextBlock
Я использую этот пример ( https://siderite.blogspot.com/2016/03/how-to-draw-outlined-text-in-wpf-and.html) для добавления контура к тексту в TextBlock. Однако этот пример не поддерживает Inlines.
Я пытаюсь добавить эту возможность, изменяя OnRender, и перебираю коллекцию Inlines, чтобы построить геометрию для каждого блока Inline. Проблема в том, что мне нужно получить позицию и размер встроенного блока в TextBlock, а не весь текст в TextBlock.
Это исходный код, который я изменил.
protected override void OnRender(DrawingContext drawingContext)
{
ensureTextBlock();
base.OnRender(drawingContext);
foreach (Inline inline in _textBlock.Inlines)
{
var textRange = new TextRange(inline.ContentStart, inline.ContentEnd);
var formattedText = new FormattedText(
textRange.Text,
CultureInfo.CurrentUICulture,
inline.FlowDirection,
new Typeface(inline.FontFamily, inline.FontStyle, inline.FontWeight, inline.FontStretch),
inline.FontSize, System.Windows.Media.Brushes.Black // This brush does not matter since we use the geometry of the text.
);
formattedText.SetTextDecorations(inline.TextDecorations);
//*****************************************************************
//This part get the size and position of the TextBlock
// Instead I need to find a way to get the size and position of the Inline block
//formattedText.TextAlignment = _textBlock.TextAlignment;
//formattedText.Trimming = _textBlock.TextTrimming;
formattedText.LineHeight = _textBlock.LineHeight;
formattedText.MaxTextWidth = _textBlock.ActualWidth - _textBlock.Padding.Left - _textBlock.Padding.Right;
formattedText.MaxTextHeight = _textBlock.ActualHeight - _textBlock.Padding.Top;// - _textBlock.Padding.Bottom;
while (formattedText.Extent == double.NegativeInfinity)
{
formattedText.MaxTextHeight++;
}
// Build the geometry object that represents the text.
var _textGeometry = formattedText.BuildGeometry(new System.Windows.Point(_textBlock.Padding.Left, _textBlock.Padding.Top));
//*****************************************************************
var textPen = new System.Windows.Media.Pen(Stroke, StrokeThickness * 2)
{
DashCap = PenLineCap.Round,
EndLineCap = PenLineCap.Round,
LineJoin = PenLineJoin.Round,
StartLineCap = PenLineCap.Round
};
var boundsGeo = new RectangleGeometry(new Rect(0, 0, ActualWidth, ActualHeight));
_clipGeometry = Geometry.Combine(boundsGeo, _textGeometry, GeometryCombineMode.Exclude, null);
drawingContext.PushClip(_clipGeometry);
drawingContext.DrawGeometry(System.Windows.Media.Brushes.Transparent, textPen, _textGeometry);
drawingContext.Pop();
}
}
Мне нужно изменить часть, которая получает размер и позицию из TextBlock, чтобы получить размер и позицию блока Inline, но я не вижу ни одного свойства Inline, которое могло бы получить эту информацию. Любая идея?
2 ответа
Я нашел способ получить позицию с помощью:
inline.ElementStart.GetCharacterRect(LogicalDirection.Forward).Left
inline.ElementStart.GetCharacterRect(LogicalDirection.Forward).Top
Затем я изменил линию, которая строит геометрию таким образом:
double posLeft = inline.ElementStart.GetCharacterRect(LogicalDirection.Forward).Left;
double posTop = inline.ElementStart.GetCharacterRect(LogicalDirection.Forward).Top;
var _textGeometry = formattedText.BuildGeometry(new System.Windows.Point(posLeft, posTop));
У меня все еще есть некоторые проблемы с переносом, потому что при переносе текста геометрия строится только в первой строке.
Попробуй это
Rect rect = Rect.Union(inline.ElementStart.GetCharacterRect(LogicalDirection.Forward),
inline.ElementEnd.GetCharacterRect(LogicalDirection.Backward));
Спасибо
Используйте свойство LineHeight TextBlock:
formattedText.LineHeight = _textBlock.LineHeight;
Таким образом, вы можете изменить значение LineHeight программно.