Edit & Format the content in the RichTextBox Windows Application through Wordpad

This tip is targeted for a specific task in vb.net. The problem, not actually a problem but the task is to edit the content in the RichTextBox of our Windows application through Wordpad and just update our control with that formatted text.

Well, the simple way to do this job is 1. Open  the Editor – wordpad. 2. Edit the textcontent 3. Copy and paste it to the textbox.

Pretty Simple.

But, let’s look into it with a different approach. And I did it something like this – 1. On Edit button click, a. Save the content of RichTextBox to a temporary “.rtf” file. b. Start a wordpad process to open this file 2. Edit the wordpad, and just close the window, saving the file.

3. As the process exits, raise the exit event of process and call a method to update the text.

And for this the code looks something like this :

Private WithEvents WordpadProcess As New Process
     Public strTempFileName As String = "C:TempDemo.rtf"
       Private Delegate Sub UpdateRichTextBox(ByVal strFileName As String)

     Private Sub btnEdit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEdit.Click
                           'Save the rich textbox content to temporary file
        rtbTextArea.SaveFile(strTempFileName, RichTextBoxStreamType.RichText)
        'Open the temporary file in Wordpad
                OpenEditor(strTempFileName)
     End Sub

    Private Sub OpenEditor(ByVal strFileName As String)
        Try
            'Open the wordpad window
            WordpadProcess.EnableRaisingEvents = True
            WordpadProcess.StartInfo.FileName = strFileName
            WordpadProcess.Start()
        Catch ex As System.Exception
            MsgBox(ex.Message, MsgBoxStyle.Information)
        End Try
    End Sub

    Private Sub WordpadProcess_Exited(ByVal sender As Object, ByVal e As System.EventArgs) Handles WordpadProcess.Exited
        Try
                    'Invoke method to update the Rich Text Box content
            Dim delUpdateRichText As UpdateRichTextBox = AddressOf UpdateTextBox
            Me.Invoke(delUpdateRichText, New Object() {"C:TempDemo.rtf"})
        Catch ex As System.Exception
            MsgBox(ex.Message, MsgBoxStyle.Information)
        End Try
    End Sub

    Private Sub UpdateTextBox(ByVal strFileName As String)
             'Update the Rich Text Box content with temporary file content
        rtbTextArea.LoadFile(strFileName, RichTextBoxStreamType.RichText)
    End Sub

So here I just want to raise two important points through this tip :
1. How can we do cross-thread update?
2. How can we track another process’ exit?

Let’s first go to the first point:

Often for a newbie, one exception is obvious for at least once while working with multithreading – “Crossthread operation not valid : Control ‘rtbTextArea’ accessed from a thread other than the thread it was created on.”

And it occurs when we try something like this in demo presented above

Private Sub WordpadProcess_Exited(ByVal sender As Object, ByVal e As System.EventArgs) Handles WordpadProcess.Exited
        Try
                                          'Update the Richtextbox on Wordpad's exited event
            rtbTextArea.LoadFile("C:TempDemo.rtf", RichTextBoxStreamType.RichText)
        Catch ex As System.Exception
            MsgBox(ex.Message, MsgBoxStyle.Information)
        End Try
    End Sub

The cause is that WordpadProcess runs in a separate thread, and we want to update the control in another running thread, i.e. our windows application. So, it simply raises a cross thread exception.  There are different ways to handle this[1], either by using BackgroundWorker or Delegates.

Here delegate approach is used to make thread safe call.
1. Define a delegate to update the textbox Private Delegate Sub UpdateRichTextBox(ByVal strFileName As String)

2. Invoke the method through delegate

Dim delUpdateRichText As UpdateRichTextBox = AddressOf UpdateTextBox

Me.Invoke(delUpdateRichText, New Object() {“C:TempDemo.rtf”})

Now  let’s think about the second point: What if we want to perform some operations that depends on some other process. The example is clear here, we want to edit the text in Wordpad and on closing the wordpad we want to update that changes to richtextbox in our application.

So, in .Net, System.Diagnostics.Process[2] class provides access and control(start/stop) to local and remote processes. We can start any process from within our application by simply calling Process.Start() method and kill the process by calling Process.Kill(). And for our purpose we can use the Exited[3] event of Process class. This event is raised whenever the target process is exited. But, it is mandatory to assign EnableRaisingEvents= true[4] for that process.

So the summerized steps are :
1. Get the process

Private WithEvents WordpadProcess As New Process
WordpadProcess.StartInfo.FileName = strFileName

2. Set EnableRaisingEvents property to True

WordpadProcess.EnableRaisingEvents = True

3. Start the Process

WordpadProcess.Start()

4. Define the Handler method to handle the exited event

Private Sub WordpadProcess_Exited(ByVal sender As Object, ByVal e As System.EventArgs) Handles WordpadProcess.Exited

References :
[1]Make Thread safe calls : http://msdn.microsoft.com/en-us/library/ms171728(v=VS.80).aspx
[2]Process Class : http://msdn.microsoft.com/en-us/library/ccf1tfx0.aspx
[3]Process.Exited Event : http://msdn.microsoft.com/en-us/library/system.diagnostics.process.exited.aspx
[4]EnableRaisingEvents : http://msdn.microsoft.com/en-us/library/system.diagnostics.process.enableraisingevents.aspx

150 150 Burnignorance | Where Minds Meet And Sparks Fly!