1
votes

WinForms, Windows 8.1

I'm trying to use a RichTextBox to highlight changes to a text file. Should be a piece of cake. I'm monitoring the text file with FileSystemWatcher, and load it in to the RichTextBox whenever the file changes.

For the highlighting, I keep track of the previous text, compare it to the current text, and anything that is in the current text that wasn't in the previous text gets highlighted. For example, if the file originally contained "one two four" and I change it to "one two three four", in the RichTextBox the word "three" will be highlighted.

What is happening is that the text is not getting highlighted UNLESS I INCLUDE EITHER MsgBox("") OR Application.DoEvents() BEFORE THE LOOP THAT DOES THE HIGHLIGHTING. Using a delay loop, or Thread.Sleep(), or RichTextBox.Invalidate, won't make it work.

NOTE: If you try and duplicate this yourself, the behavior only appears when I obtain the text from the file. If I put a TextBox and Button on the form, and update RichTextBox.Text with TextBox.Text on Button.Click, the code works as it should.

Public Class Form1
    Public sCurrentDir As String = My.Computer.FileSystem.CurrentDirectory
    Public sCurrent As String = ""
    Public sPrevious As String = ""


    '******************************************************
    Private Function FileIsOpen(sFile)
        Try
            Dim FS As IO.FileStream = IO.File.Open(sFile, IO.FileMode.Open, IO.FileAccess.Read, IO.FileShare.None)  'Create file stream with read-only exclusive access

            FS.Close()
            FS.Dispose()
            FS = Nothing

            Return False
        Catch ex As IO.IOException
            Return True
        Catch ex As Exception
            MessageBox.Show("Error: " & ex.Message)

            Return True
        End Try
    End Function


    '******************************************************
    Private Sub FileSystemWatcher1_Changed(sender As Object, e As IO.FileSystemEventArgs) Handles FileSystemWatcher1.Changed
        Do Until Not FileIsOpen(sCurrentDir & "\test.txt")
        Loop

        RichTextBox1.Text = IO.File.ReadAllText(sCurrentDir & "\test.txt")
    End Sub


    '******************************************************
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        RichTextBox1.Text = IO.File.ReadAllText(sCurrentDir & "\test.txt")
    End Sub


    '******************************************************
    Private Sub RichTextBox1_TextChanged(sender As Object, e As EventArgs) Handles RichTextBox1.TextChanged
        Dim aCurrent(), aPrevious()
        Dim i As Integer

        If (RichTextBox1.Text <> sCurrent) Then  'Text is different (rather than simply being replaced with the same text)
            'Erase previous selection(s)
            RichTextBox1.SelectedText = ""
            RichTextBox1.SelectAll()
            RichTextBox1.SelectionBackColor = RichTextBox1.BackColor

            sPrevious = sCurrent
            sCurrent = RichTextBox1.Text

            aCurrent = Split(sCurrent)
            aPrevious = Split(sPrevious)

            'This DOES make the highlighting code work
            'MsgBox("")

            'This DOES make the highlighting code work
            'Application.DoEvents()

            'This does NOT make the highlighting code work
            'System.Threading.Thread.Sleep(1000)

            'This does NOT make the highlighting code work
            'For i = 0 To 500000
            'Next

            For i = 0 To aCurrent.Count - 1
                If (sPrevious.IndexOf(aCurrent(i)) = -1) Then
                    RichTextBox1.Select(RichTextBox1.Text.IndexOf(aCurrent(i)), Len(aCurrent(i)))

                    RichTextBox1.SelectionBackColor = Color.Yellow
                End If
            Next

            'This does NOT make the highlighting code work
            'RichTextBox1.Invalidate()

            RichTextBox1.SelectionLength = 0  'Otherwise the last selected word will still be selected
        End If
    End Sub
End Class
1
But A) the issue doesn't occur if I update the the RichTextBox with local text say, via a Button.Click event; it is only happening when I read it from the file; and B) putting MsgBox or DoEvents before the loop shouldn't have any effect on the loop freezing the GUI. (And why wouldn't the OS process the backed up messages after loop completion?) Putting MsgBox or DoEvents -- which I would think would force the OS to process any backed-up messages -- after the loop also does not cause the code to highlight properly.Brian

1 Answers

0
votes

By trying to open the test file, you are causing the FileChanged event to fire, which causes the code to try to open the test file, which causes the FileChanged event to fire, etc, etc.

The loop seems unnecessary or you need to turn off the events with the EnableRaisingEvents property of the FileSystemWatcher.