2011-05-27 105 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