如何在不选择 RichTextBox 的情况下恢复插入符号位置或更改文本颜色

Posted

技术标签:

【中文标题】如何在不选择 RichTextBox 的情况下恢复插入符号位置或更改文本颜色【英文标题】:How to restore Caret position or Change color of text without making a selection in RichTextBox 【发布时间】:2014-08-12 20:46:08 【问题描述】:

这一直是我的许多应用程序的一个问题,我不知道为什么 Windows 没有一个优雅的解决方案。

我在 VS2013 的 .Net 4.5 中使用 Winforms

例如,我想更改多行 RichTextBox 中一行文本的颜色。

为此,我需要使用类似

的方式设置选择
rtb.Select(rtb.GetFirstCharIndexFromLine(r), str.Length);

然后,我将使用

设置颜色
rtb.SelectionColor = Color.Red;

大概,用

取消选择
rtb.DeselectAll();

现在的问题是光标/插入符号已移回行首,

我尝试通过保存以前的插入符号位置来修复它,

rtb.CaretPosition

但是,CaretPosition 不是 RichTextBox 的方法,在网上到处都是大家使用的主要方法。

我尝试将 PresentationFramework 添加到我的引用和我添加的代码中

using System.Windows.Framework;

这里建议:http://msdn.microsoft.com/en-us/library/system.windows.controls.richtextbox.caretposition(v=vs.110).aspx

但我仍然没有看到 CaretPosition 属性,只有 ScrollToCaret() 方法。

我的两个问题是:

    如何在我的 RichTextBox 中获取 CaretPosition 属性?

    如何在不使用选择和影响插入符号位置的情况下更改文本颜色,必须编写复杂的逻辑来为用户恢复它。

我的应用程序检查序列号,每行一个,如果它们与格式不匹配,则将其突出显示为红色,如下所示。

private void rtb_TextChanged(object sender, EventArgs e)
    
        string pattern = @"[A-Z]2[A-Z, 0-9]2\d4";
        Regex rgx = new Regex(pattern, RegexOptions.IgnoreCase);

        TextReader read = new System.IO.StringReader(rtb.Text);
        SerialNumbers.Clear();
        int selectStart = 0;

        for (int r = 0; r < rtb.Lines.Length; r++)
        
            string str = read.ReadLine();

            if (str != null)
            

                selectStart += str.Length;
                MatchCollection matches = rgx.Matches(str);
                if (matches.Count == 1)
                
                    SerialNumbers.Add(str);
                
                else
                
                    rtb.Select(rtb.GetFirstCharIndexFromLine(r), str.Length);
                    rtb.SelectionColor = Color.Red;
                    rtb.DeselectAll();
                

            
        
     

【问题讨论】:

该文档适用于 WPF RichTextBox,您使用的是 Windows 窗体。 ***.com/questions/2241862/… 【参考方案1】:

您应该使用SelectionCaret(正如评论中提到的@Mangist),因为您使用的是WinForms 而不是WPF。您引用的 MSDN 文章仅适用于 WPF,与 WinForms 有很大不同。

例如,我使用以下内容从 WinForms 应用程序中的任何位置轻松登录到富文本框:

public static void Log(string text, ref RichTextBox rtbLogBox) 
    //
    if (text == null) return;

    var timestamp = DateTime.Now.ToLongTimeString();
    var logtext = string.Format("0    -   1\r\n\r\n", timestamp, text);
    if (rtbLogBox.InvokeRequired) 
        var logBox = rtbLogBox;
        logBox.Invoke(new MethodInvoker(delegate 
            logBox.AppendText(logtext);
            logBox.Update();
            logBox.SelectionStart = logBox.Text.Length;
            logBox.ScrollToCaret();
        ));
     else 
        rtbLogBox.AppendText(logtext);
        rtbLogBox.Update();
        rtbLogBox.SelectionStart = rtbLogBox.Text.Length;
        rtbLogBox.ScrollToCaret();
    

注意在将SelectionStart 设置为富文本框中的文本长度后如何调用ScrollToCaret()。这解决了AppendText在添加文本后不滚动到底部的“问题”。

在您的情况下,您只需在使用突出显示格式化文本之前保存 SelectionStart 值,然后在完成后恢复它。

【讨论】:

对不起,这似乎并没有帮助。即使我将 SelectionStart 与 ScrollToCaret 结合使用,插入符号也总是移动到我正在输入的文本的开头。当我使用 Select 方法时,我也会做同样的事情。至少我希望它滚动到文本的末尾,或者滚动到最后一个键入的字符的末尾。【参考方案2】:

通过保存 SelectionStart 位置来修复它

                int selectionStart = SNbox.SelectionStart;

                SNbox.Select(SNbox.GetFirstCharIndexFromLine(r), str.Length);
                SNbox.SelectionColor = Color.Red;
                SNbox.DeselectAll();

                SNbox.SelectionStart = selectionStart;
                SNbox.SelectionLength = 0;

【讨论】:

以上是关于如何在不选择 RichTextBox 的情况下恢复插入符号位置或更改文本颜色的主要内容,如果未能解决你的问题,请参考以下文章

通知意图 - 如何在不重置的情况下恢复通知中的活动?

如何在不进行任何更改的情况下恢复推送的合并?

如何在不闪烁和布局重叠的情况下恢复和最大化表单?

如何在不挂起的情况下返回并恢复我的应用程序?

Git - 如何在不快速转发和合并为当前的情况下恢复以前的提交

java.sql.SQLException: Io 异常: Broken pipe 如何在不重启的情况下恢复?