检测RichTextBox中的强制行分割

问题描述 投票:0回答:1

我有一个应用程序以管道格式(HL7)分析数据消息,为此,它具有与DataGridView同步的RichTextBox。具体来说,当您单击DataGridView中的属性时,它会跳到RichTextBox中的相应位置,反之亦然。

RichTextBox禁用了自动换行,因此我可以轻松地将编辑器中的行与实际数据中的行进行匹配。

但是,我目前必须处理其中某些部分包含二进制文件的Base64转储的消息,而大量的内容使富文本框仍然可以换行。这使计算变得混乱,当与实际消息文本中的返回位置匹配时,我得到了错误的数据,分析失败了,通常,当实际下一行短于所单击位置时,我得到一个ArgumentOutOfRangeException那条线。

这是代码:

/// <summary>Gets the cursor position as Point, with Y as line number and X as index on that line.</summary>
/// <returns>The cursor position as Point, with Y as line number and X as index on that line</returns>
protected Point GetCursorPosition()
{
    Int32 selectionStart = this.rtxtMessage.SelectionStart;
    Int32 currentLine = this.rtxtMessage.GetLineFromCharIndex(selectionStart);
    Int32 currentPos = selectionStart - this.rtxtMessage.GetFirstCharIndexFromLine(currentLine);
    return new Point(currentPos, currentLine);
}

正确的行为:“更正”

单击此函数将返回点[28,4]。

强制包装线上的错误行为:“不正确”

在此单击上,该函数将返回点[6,5],该点实际上应为[2813,4]。这将导致它显示对下一行的分析,并且如上所述,如果单击是在该行中超出下一个分析行的末尾的位置,则会导致ArgumentOutOfRangeException

有什么方法可以补偿这种强制性的分线吗?我需要能够准确确定实际文本中的位置以进行分析。

注意,行拆分似乎不可预测;我不知道尝试分割的最大长度是多少,或者决定分割的字符是可能的。

[还要注意,两个称为RichTextBox的函数,即GetLineFromCharIndexGetFirstCharIndexFromLine,正确地对应于屏幕上实际显示的内容...但是屏幕上显示的内容是对真实数据的错误表示。实际上,它甚至不对应于RichTextBox自己的.Lines属性的输出,这为我提供了纯文本行数组中的内容。

但是,我宁愿避免使用该.Lines属性,因为我注意到一般来说,从富文本框中提取文本的功能相当慢。

c# winforms richtextbox
1个回答
0
投票
但是,这使我意识到整个项目中我的代码的[[lot正在

已经访问该属性以进行随机操作,尤其是在发生任何行更改的分析部分。

我决定为该行数组设置一个缓存变量,该变量在TextChangedRichTextBox事件中被清除。然后,将所有提取了RichTextBox上的行的实例替换为对该小函数的调用:

private String[] GetTextboxLines() { if (this.m_LineCache != null) return this.m_LineCache; String[] lines = this.rtxtMessage.Lines; this.m_LineCache = lines; return lines; } 仅在富文本编辑器中键入文本时,这仍然很繁重,因为任何按键都会基本上清除数组,然后分析器操作将再次读取该数组,但是由于该工具首先是分析器,然后才是编辑器,这不是一个大问题。即便如此,在这样的按键之后,RichTextBox.Lines在分析中也被多次调用,因此总体上,结果[大大优化了。]

有了这个系统,在我的小GetCursorPosition()函数中再次使用lines数组变得可行,因此我也对其进行了调整,以利用新的缓存值:

    /// <summary>Gets the cursor position as Point, with Y as line number and X as index on that line.</summary>
    /// <returns>The cursor position as Point, with Y as line number and X as index on that line</returns>
    protected Point GetCursorPosition()
    {
        Int32 selectionStart = this.rtxtMessage.SelectionStart;
        String[] lines = this.GetTextboxLines();
        Int32 nrOfLines = lines.Length;
        Int32 y;
        for (y = 0; y < nrOfLines; y++)
        {
            Int32 lineLen = lines[y].Length;
            // Can be equal if at the very end of a line.
            if (selectionStart <= lineLen)
                return new Point(selectionStart, y);
            // +1 to compensate for the line break character,
            // which is only one byte in a rich text box.
            selectionStart -= (lineLen + 1);
        }
        return new Point(0, nrOfLines - 1);
    }
© www.soinside.com 2019 - 2024. All rights reserved.