简体   繁体   English

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

[英]How to draw border around a word in RichTextBox?

Let's say I have 2 TextPointers.假设我有 2 个 TextPointers。 One pointing at the beginning of a word and the other at the end of the word.一个指向词首,另一个指向词尾。

I would like to draw single pixel border around the word.我想在单词周围绘制单个像素边框。 How would I go about this?我将如何 go 关于这个? The border should be tied to the word and move with it when user types or scrolls..当用户键入或滚动时,边框应与单词绑定并随之移动。

I already tried TextDecorations with DrawingBrush but couldn't come up with anything usable.我已经用 DrawingBrush 尝试了 TextDecorations,但没有想出任何可用的东西。

I have done something similar, only underlining text in a TextBox.我做了类似的事情,只是在 TextBox 中为文本加下划线。 The principal seems to be mostly the same.校长似乎大多相同。

  1. Add an AdornerDecorator containing your RichTextBox but inside a ScrollViewer.添加包含 RichTextBox 但在 ScrollViewer 内的 AdornerDecorator。

     <Border...> <ScrollViewer... > <AdornerDecorator> <RichTextBox x:Name="superMagic" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden" BorderBrush="{x:Null}" BorderThickness="0"... /> </AdornerDecorator> </ScrollViewer> </Border>
  2. Create an Adorner to render the rectangle and add it to the AdornerLayer创建一个 Adorner 来渲染矩形并将其添加到 AdornerLayer

     void HostControl_Loaded(object sender, RoutedEventArgs e) { _adorner = new RectangleAdorner(superMagic); AdornerLayer layer = AdornerLayer.GetAdornerLayer(superMagic); layer.Add(_adorner); }
  3. The adorner should hook the TextChanged event of the RichTextBox.装饰器应挂钩 RichTextBox 的 TextChanged 事件。 All you need to do is call InvalidateVisuals() via the dispatcher using DispatcherPriority.Background to ensure it is rendered after the text box.您需要做的就是使用DispatcherPriority.Background通过调度程序调用InvalidateVisuals()以确保它在文本框之后呈现。 I don't know if it's an issue for the RichTextBox , but getting the character coordinates from a TextBox is only possible if it has been rendered at least once since it's content last changed.我不知道这是否是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. Override Adorner.OnRender() to draw the box using TextPointer.GetCharacterRect() to get the coordinates.覆盖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)); }

Note: Although the original code worked well, I wrote it a long time ago and have not tested my adaptions for this answer.注意:虽然原始代码运行良好,但我很久以前就写过了,还没有测试我对这个答案的改编。 It should at least help put you on the right path.它至少应该帮助你走上正确的道路。

Also, this does not handle cases where the word is split across lines, but shouldn't be too hard to cater for.此外,这不处理单词跨行拆分的情况,但不应该太难满足。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM