2011-05-27 71 views
9

比方说,我有2个TextPointers。一个指向一个词的开头,另一个指向词尾。如何在RichTextBox中围绕单词绘制边框?

我想在单词的周围绘制单个像素边框。我会怎么做呢?当用户键入或滚动时,应将边框绑定到该单词上并随其移动。

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

回答

7

我做了类似的事情,只在文本框中加下划线。校长似乎大部分是一样的。

  1. 添加包含您的RichTextBox的AdornerDecorator但里面的ScrollViewer。

    <Border ...> 
        <ScrollViewer ... > 
         <AdornerDecorator> 
          <RichTextBox 
           x:Name="superMagic" 
           HorizontalScrollBarVisibility="Hidden" 
           VerticalScrollBarVisibility="Hidden" 
           BorderBrush="{x:Null}" 
           BorderThickness="0" 
           ... 
           /> 
         </AdornerDecorator> 
        </ScrollViewer> 
    </Border> 
    
  2. 创建一个装饰器来呈现矩形,并把它添加到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)); 
    } 
    

注:尽管最初的代码工作很好,我很久以前写的,并没有测试我adaptions了这个答案。它至少应该帮助你走上正确的道路。

而且,这种不处理,其中字拆分为多行的情况,但不应该太难应付。

+0

好我会测试这个。 – Kugel 2011-05-28 19:36:11

+0

完美的作品! :) – JanDotNet 2017-01-06 13:26:05