如何使用c#.net在richtextbox中获取特定的彩色单词

时间:2014-07-31 19:18:05

标签: c# richtextbox

我想选择richtextbox中有蓝色的所有单词。我怎样才能做到这一点? 在richtextbox中,有一些蓝色关键字。我希望将所有这些关键字作为一个集合。

1 个答案:

答案 0 :(得分:1)

通过"选择",我认为你的意思是"找到"。我不相信您可以在RichTextBox中实际选择多个不连续的文本范围。

假设我的理解是正确的,这里有一些经过适度测试的代码,我最近一直在努力。让我知道它对你有用。

请注意,RichTextBox中的所有文字内容实际上都存储在FlowDocument中,可通过Document属性访问。要遍历字符串,您需要在TextElement中遍历FlowDocument类的层次结构。下面这样做,返回每个字符串和表示层次结构的堆栈,可能由选择器方法转换:

    public static IEnumerable<KeyValuePair<Stack<T>, string>> WalkTextElements<T>(FlowDocument doc, Func<DependencyObject, Stack<T>, T> selector)
    {
        // Inspiration: http://www.bryanewert.net/journal/2010/5/26/how-to-explore-the-contents-of-a-flowdocument.html
        if (doc != null)
        {
            var stack = new Stack<T>();
            // Start with a TextPointer to FlowDocument.ContentStart
            TextPointer t = doc.ContentStart;

            // Keep a TextPointer for FlowDocument.ContentEnd handy, so we know when we're done.
            TextPointer e = doc.ContentEnd;

            // Keep going until the TextPointer is equal to or greater than ContentEnd.
            while ((t != null) && (t.CompareTo(e) < 0))
            {
                // Identify the type of content immediately adjacent to the text pointer.
                TextPointerContext context = t.GetPointerContext(LogicalDirection.Forward);

                // ElementStart is an "opening tag" which defines the structure of the document, e.g. a paragraph declaration.
                if (context == TextPointerContext.ElementStart)
                {
                    stack.Push(selector(t.Parent, stack));
                }
                // An EmbeddedElement, e.g. a UIContainer.
                else if (context == TextPointerContext.EmbeddedElement)
                {
                    ; // Do nothing.
                }
                // The document's text content.
                else if (context == TextPointerContext.Text)
                {
                    stack.Push(selector(t.Parent, stack));
                    yield return new KeyValuePair<Stack<T>, string>(stack, t.GetTextInRun(LogicalDirection.Forward));
                    stack.Pop();
                }
                // ElementEnd is a "closing tag".
                else if (context == TextPointerContext.ElementEnd)
                {
                    stack.Pop();
                }
                else
                {
                    throw new System.Exception("Unhandled TextPointerContext " + context.ToString());
                }

                // Advance to the next ContentElement in the FlowDocument.
                t = t.GetNextContextPosition(LogicalDirection.Forward);
            }
        }
    }

有了这个,我们可以枚举显式重写背景颜色的字符串:

    /// <summary>
    /// Enumerate all the strings in a given flow document that are have an explicit background color.
    /// </summary>
    /// <param name="doc"></param>
    /// <param name="includeFlowDocumentColor">true to consider overrides on the entire FlowDocument itself, else false.</param>
    /// <returns></returns>
    public static IEnumerable<KeyValuePair<Brush, string>> WalkBackgroundColoredTexts(FlowDocument doc, bool includeFlowDocumentColor)
    {
        foreach (var pair in WalkTextElements<Brush>(doc, (d, s) => SelectTextBackgroundBrush(d, s, includeFlowDocumentColor)))
        {
            var brush = pair.Key.Peek();
            if (brush != null)
            {
                yield return new KeyValuePair<Brush, string>(brush, pair.Value);
            }
        }
    }

    static Brush SelectTextBackgroundBrush(DependencyObject element, Stack<Brush> brushes, bool includeFlowDocumentColor)
    {
        //http://blogs.msdn.com/b/prajakta/archive/2006/10/11/flowdocument-content-model.aspx
        //http://msdn.microsoft.com/en-us/library/aa970786%28v=vs.110%29.aspx
        var textElement = element as TextElement;
        if (textElement != null)
        {
            var brush = textElement.Background;
            if (brush != null)
                return brush;
            return PeekOrDefault(brushes);
        }
        var tableColumn = element as TableColumn;
        if (tableColumn != null)
        {
            var brush = tableColumn.Background;
            if (brush != null)
                return brush;
            return PeekOrDefault(brushes);
        }
        if (includeFlowDocumentColor)
        {
            var doc = element as FlowDocument;
            if (doc != null)
            {
                var brush = doc.Background;
                if (brush != null)
                    return brush;
                return PeekOrDefault(brushes);
            }
        }
        return null;
    }

    static T PeekOrDefault<T>(Stack<T> stack)
    {
        return (stack.Count == 0 ? default(T) : stack.Peek());
    }

您可能希望忽略流文档本身设置的背景颜色,并仅获取具有背景颜色集的特定文本运行,这就是我添加参数的原因。

鉴于字符串,您可能仍需要将它们标记为单词。