比方说,我有2个TextPointers。一个指向一个词的开头,另一个指向词尾。如何在RichTextBox中围绕单词绘制边框?
我想在单词的周围绘制单个像素边框。我会怎么做呢?当用户键入或滚动时,应将边框绑定到该单词上并随其移动。
我已经使用DrawingBrush尝试过TextDecorations,但无法提供任何可用的东西。
比方说,我有2个TextPointers。一个指向一个词的开头,另一个指向词尾。如何在RichTextBox中围绕单词绘制边框?
我想在单词的周围绘制单个像素边框。我会怎么做呢?当用户键入或滚动时,应将边框绑定到该单词上并随其移动。
我已经使用DrawingBrush尝试过TextDecorations,但无法提供任何可用的东西。
我做了类似的事情,只在文本框中加下划线。校长似乎大部分是一样的。
添加包含您的RichTextBox的AdornerDecorator但里面的ScrollViewer。
<Border ...>
<ScrollViewer ... >
<AdornerDecorator>
<RichTextBox
x:Name="superMagic"
HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Hidden"
BorderBrush="{x:Null}"
BorderThickness="0"
...
/>
</AdornerDecorator>
</ScrollViewer>
</Border>
创建一个装饰器来呈现矩形,并把它添加到AdornerLayer
void HostControl_Loaded(object sender, RoutedEventArgs e)
{
_adorner = new RectangleAdorner(superMagic);
AdornerLayer layer = AdornerLayer.GetAdornerLayer(superMagic);
layer.Add(_adorner);
}
装饰器应该勾在RichTextBox的TextChanged事件。您只需通过调度员使用DispatcherPriority.Background
调用InvalidateVisuals()
,以确保它在文本框之后呈现。我不知道这是否是为RichTextBox
的问题,但得到的字符从TextBox
坐标是唯一可能的,如果它已经呈现至少一次,因为它的内容最后改变。
class RectangleAdorner : Adorner
{
public RectangleAdorner(RichTextBox textbox)
: base(textbox)
{
textbox.TextChanged += delegate
{
SignalInvalidate();
};
}
void SignalInvalidate()
{
RichTextBox box = (RichTextBox)this.AdornedElement;
box.Dispatcher.BeginInvoke(DispatcherPriority.Background, (Action)InvalidateVisual);
}
// ...
}
覆盖Adorner.OnRender()
使用TextPointer.GetCharacterRect()
得到的坐标绘制框。
protected override void OnRender(DrawingContext drawingContext)
{
TextPointer start;
TextPointer end;
// Find the start and end of your word
// Actually, if you did this in the TextChanged event handler,
// you could probably save some calculation time on large texts
// by considering what actually changed relative to an earlier
// calculation. (TextChangedEventArgs includes a list of changes
// - 'n' characters inserted here, 'm' characters deleted there).
Rect startRect = start.GetCharacterRect(LogicalDirection.Backward);
Rect endRect = end.GetCharacterRect(LogicalDirection.Forward);
drawingContext.DrawRectangle(null, pen, Rect.Union(startRect, endRect));
}
注:尽管最初的代码工作很好,我很久以前写的,并没有测试我adaptions了这个答案。它至少应该帮助你走上正确的道路。
而且,这种不处理,其中字拆分为多行的情况,但不应该太难应付。
好我会测试这个。 – Kugel 2011-05-28 19:36:11
完美的作品! :) – JanDotNet 2017-01-06 13:26:05