6

以下代码旨在在ReadOnlyRichTextBox 中维护一个文本缓冲区,其中存储了最大数量的字符,并且始终保持滚动到底部。它流式传输实时日志。

但是在我试图保持最大字符数的过程中,rtMessages.TextLength()之后并没有改变rtMessages.SelectedText = String.Empty,因此,如果没有防御If块,我最终会出现一个无限循环,试图重复删除缓冲区的第一行。

当我删除ReadOnly-ness 时RichTextBox,此功能成功。似乎有点奇怪,既然AppendText成功了,但我明白选择是另一种野兽。

我可以让它以ReadOnly RichTextBox编程方式修改吗?

Private Sub onNewData(ByRef data As String) Handles _server.clientSentData

    ' Add new text
    rtMessages.SelectionStart = rtMessages.TextLength()
    rtMessages.AppendText(data)

    ' Delete oldest text line-by-line until the whole buffer is shorter than MAX_TEXT_LENGTH characters
    Const MAX_TEXT_LENGTH = 200
    Dim textLength = rtMessages.TextLength()
    While textLength > MAX_TEXT_LENGTH
        Dim i As Int16 = 0
        Do While rtMessages.GetLineFromCharIndex(i) < 1
            i += 1
        Loop

        rtMessages.Select()
        rtMessages.SelectionStart = 0
        rtMessages.SelectionLength = i
        rtMessages.SelectedText = String.Empty
        rtMessages.SelectionLength = 0

        If rtMessages.TextLength() = textLength Then
            rtMessages.Clear()
            rtMessages.AppendText("[buffer trimming algorithm failed]")
            Exit While
        End If

        textLength = rtMessages.TextLength()
    End While

    ' Scroll down
    rtMessages.SelectionStart = rtMessages.TextLength()
    rtMessages.ScrollToCaret()
End Sub
4

4 回答 4

5

虽然尝试在 ReadOnly RichTextBox 中替换 SelectedText 不起作用,但使用 SelectedRtf 确实有效:

  'rtMessages.Select()
  'rtMessages.SelectionStart = 0
  'rtMessages.SelectionLength = i
  'rtMessages.SelectedText = String.Empty
  'rtMessages.SelectionLength = 0

  rtMessages.Select(0, i)
  rtMessages.SelectedRtf = "{\rtf1\ansi}"
于 2013-10-30T17:17:13.253 回答
0
rtMessages.SelectionLength = i - 1

应该替换为

rtMessages.SelectionLength = i

编辑#1

通过将 -1 添加到 SelectionLength,您将丢失第一行的最后一个字符。第二次运行时,第一行只有一个字符(第一次运行时错过的那个)。然后,您将尝试删除 0 的 SelectionLength,并且每隔一次运行您将获得相同的 TextLength,然后您将进入无限循环!

于 2012-11-10T01:43:11.113 回答
0

您可以删除只读参数,编写 appendtext 代码,然后再次将 Richtextbox 设为只读。

于 2013-04-29T05:01:41.367 回答
0

我知道这是一个旧线程,但您可以通过ReadOnly替换以下代码来解决这个问题:

 rtMessages.Select()
 rtMessages.SelectionStart = 0
 rtMessages.SelectionLength = i
 rtMessages.SelectedText = String.Empty
 rtMessages.SelectionLength = 0

有了这个:

 rtMessages.Text = rtMessages.Text.Substring(i)

我不确定这是更好还是更差的性能,但它绕过了RichTextBox被设置为ReadOnly

编辑:

这是用于测试的完整代码(注意:我将代码添加到 aButton.Click进行测试)

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    Static X As Integer = 0
    X += 1

    Dim Data As String = "Line " & X.ToString & ControlChars.NewLine
    Me.onNewData(Data)
End Sub

Private Sub onNewData(ByRef data As String)

    ' Add new text
    rtMessages.SelectionStart = rtMessages.TextLength()
    rtMessages.AppendText(data)

    ' Delete oldest text line-by-line until the whole buffer is shorter than MAX_TEXT_LENGTH characters
    Const MAX_TEXT_LENGTH As Integer = 200
    Dim textLength As Integer = rtMessages.TextLength()
    While textLength > MAX_TEXT_LENGTH
        Dim i As Integer = 0
        Do While rtMessages.GetLineFromCharIndex(i) < 1
            i += 1
        Loop

        'rtMessages.Select()
        'rtMessages.SelectionStart = 0
        'rtMessages.SelectionLength = i
        'rtMessages.SelectedText = String.Empty
        'rtMessages.SelectionLength = 0

        rtMessages.Text = rtMessages.Text.Substring(i)

        If rtMessages.TextLength() = textLength Then
            rtMessages.Clear()
            rtMessages.AppendText("[buffer trimming algorithm failed]")
            Exit While
        End If

        textLength = rtMessages.TextLength()
    End While

    ' Scroll down
    rtMessages.SelectionStart = rtMessages.TextLength()
    rtMessages.ScrollToCaret()

End Sub
于 2013-10-30T17:02:44.133 回答