2012-11-10 113 views
5

下面的代碼旨在保留一個文本緩衝區在一個ReadOnly RichTextBox中,最大數量的字符存儲,並始終保持滾動到底部。它傳輸實時日誌。如何以編程方式從ReadOnly RichTextBox中刪除文本?

但在我試圖保持最大字符數,rtMessages.TextLength()rtMessages.SelectedText = String.Empty因此之後沒有改變,沒有防守If塊,我結束了一個無限循環試圖多次刪除緩衝區的第一行。

當我刪除RichTextBoxReadOnly時,此功能成功。似乎有點奇怪,因爲AppendText成功,但我明白,選擇是一個不同的野獸。

我可以讓這個一個ReadOnlyRichTextBox編程修改?

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 
+0

我可以確認這個'Sub'正在UI線程上調用,而不是一些通信線程。 –

+1

+1,因爲問題不像看起來那麼簡單...我很羨慕沒有人在SO上提到過這一點。 –

回答

2

雖然試圖取代SelectedText在一個只讀的RichTextBox不工作,使用SelectedRtf做工作:

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

    rtMessages.Select(0, i) 
    rtMessages.SelectedRtf = "{\rtf1\ansi}" 
+0

我會在緩衝區的開始處添加大量的{\ rtf1 \ ansi}代碼點,還是會崩潰/被忽略? –

+0

@LightnessRacesinOrbit它們將被取消。 RTB「合併」RTF文件。 – LarsTech

+0

那麼我們去那麼:)謝謝 –

0
rtMessages.SelectionLength = i - 1 

應該

rtMessages.SelectionLength = i 

編輯#1

代替通過添加-1到SelectionLength,你錯過了第一行的最後一個字符。第二次運行時,第一行中只有1個字符(第一次運行時錯過的那個字符)。然後,您將嘗試刪除SelectionLength爲0,並且您將爲其他所有運行獲得相同的TextLength,然後您將使用無限循環!

+0

你說得對。不過這並不是問題所在。 –

+0

你確定嗎?我把你的bug重現在我身邊,改變這條線對我來說是個訣竅。 –

+0

當我更改代碼時,錯誤仍然存​​在,直到我關閉「ReadOnly」。每次迭代都給了我相同的TextLength,而不是除了第一次迭代以外的每次迭代。 –

0

您可以刪除只讀參數,編寫附加的文本代碼,然後再次將richtextbox設置爲只讀。

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 
+0

在某些情況下,我認爲可行的解決方法,但我的緩衝區很大;這也打破了當前的滾動位置。 –

+0

@LightnessRacesinOrbit,滾動位置是不是由'rtMessages.SelectionStart = rtMessages.TextLength()'和'rtMessages.ScrollToCaret()'重置?在我的測試中,它滾動得很好。你使用什麼尺寸的緩衝區? – Grahamvs

+0

我其實沒有現在的代碼,所以它是來自內存的猜測,但我的記憶說,用新文本替換整個文本緩衝區失去了舊的滾動位置。這不是嗎?緩衝區將高達10KB左右的IIRC。 –

相關問題