6

次のコードは、RichTextBox 内のテキスト バッファーを維持ReadOnlyし、最大数の文字を格納し、常に一番下までスクロールすることを目的としています。リアルタイム ログをストリーミングします。

しかし、最大文字数を維持しようとすると、rtMessages.TextLength()後で変更されrtMessages.SelectedText = String.Emptyないため、防御Ifブロックがなければ、バッファの最初の行を繰り返し削除しようとする無限ループになってしまいます。

ReadOnlyの-nessを削除するとRichTextBox、この機能は成功します。AppendText成功するので、少し奇妙に思えますが、選択が別の獣であることは理解しています。

ReadOnly RichTextBoxaをプログラムで変更できるようにすることはできますか?

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

これが古いスレッドであることは承知していますがReadOnly、次のコードを置き換えることで問題を回避できます。

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

これとともに:

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

これがパフォーマンスの良し悪しであるかどうかはわかりませんが、次のRichTextBoxように設定されていることを回避しますReadOnly

編集:

これをテストするために使用した完全なコードを次に示します (注:Button.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 に答える
0
rtMessages.SelectionLength = i - 1

に置き換える必要があります

rtMessages.SelectionLength = i

編集#1

-1 を SelectionLength に追加すると、最初の行の最後の文字が失われます。2 回目の実行では、最初の行に 1 文字だけが表示されます (最初の実行で見逃した文字)。次に、0 の SelectionLength を削除しようとすると、他の実行ごとに同じ TextLength が得られ、無限ループが発生します。

于 2012-11-10T01:43:11.113 に答える
0

読み取り専用パラメーターを削除し、appendtext コードを記述してから、richtextbox を再度読み取り専用にすることができます。

于 2013-04-29T05:01:41.367 に答える