如何在RichTextBox中的单词周围绘制边框?

假设我有2个TextPointers。 一个指向单词的开头,另一个指向单词的结尾。

我想在单词周围绘制单个像素边框。 我怎么会这样呢? 边框应该与单词绑定,并在用户输入或滚动时随之移动。

我已经尝试过使用DrawingBrush的TextDecorations但是无法提供任何可用的东西。

我做了类似的事情,只在TextBox中加下了文字。 校长似乎大致相同。

  1. 添加包含RichTextBox但在ScrollViewer中的AdornerDecorator。

           
  2. 创建一个Adorner来渲染矩形并将其添加到AdornerLayer

     void HostControl_Loaded(object sender, RoutedEventArgs e) { _adorner = new RectangleAdorner(superMagic); AdornerLayer layer = AdornerLayer.GetAdornerLayer(superMagic); layer.Add(_adorner); } 
  3. 装饰器应该挂钩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); } // ... } 
  4. 覆盖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)); } 

注意:虽然原始代码运行良好,但我很久以前就已经写好了,并没有测试我对这个答案的适应性。 它至少应该帮助你走上正确的道路。

此外,这不处理单词跨行分割的情况,但不应该太难以满足。