Visual Basic Spell Check Enabled Rich Text Box Custom Control

Introduction:

This article describes a quick and simple approach to applying a spell check function to the rich text box control and bundling both features into a single custom control. Of course there is nothing novel or particularly interesting about performing spell checking upon a selection of text using the Word.DLL, it has been done many times and there is nothing new here with regards to the details of the mechanization I've used other than the fact that it is all contained within a custom control. 

My interest in building this control was two-fold; first I wanted the functionality placed into a custom control so that is might more easily be dropped into multiple locations in a form used to collect narrative information from the user, and the second element of interest was to answer the question as to whether or not the control would function on systems equipped with either Word 2003 or Word 2007. 

With regards to the two versions of Word; I was able to run the control on systems equipped with either Microsoft Word 2003 or 2007 and on both Vista and XP.  It does seem that an application built using the control will at least survive the transition from Microsoft Word 2003 to Microsoft Word 2007.

Image1.jpg
Figure 1: RTB with Spell Check Custom Control in Use.

Getting Started:

In order to get started, fire up the Visual Studio 2005 IDE and open the attached solution. The solution consists of a Win Forms project with a single form and a control project containing a single custom control. The Win Forms project main form is used as a test bed for the custom control and the custom control is an extension of the standard windows forms rich text box control. 

Figure 2 shows the solution explorer for this project, note the addition of the references to Microsoft Office contained in the control project:

solution-explorer-in-vb.net.jpg
Figure 2:  Solution Explorer
 

The Code:  Main Form

The main form of the application serves only as a test project for the Spell Check custom control; the project contains only a single form and that form contains only a toolbar and the custom control.  The tool bar contains only the controls necessary to open or save a file from the extended rich text box control, to execute the command to spell check the contents of the rich text box, and to exit the application.

The code contained in the form follows; in imports are in the default configuration with one exception which was the addition of the System.IO library which is used to support opening and closing files. The namespace and class declarations are in the default configuration. 

Public Class Form1
 

The next section of code is used to declare a string variable used to contain the path to the current file. The constructor follows this variable declaration and it is in the default configuration.

 

 

' String pointing the file path of the current file

Private currentFile As String = String.Empty      

 

 


public Form1()

{

    InitializeComponent();

 

The next section of code contained in the demo application is the click event handler used to command the custom control to execute the Check Spelling function.  This function will launch the Word based spell check function against the contents of the control's rich text box.

 

 

Private Sub tspSpellCheck_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)Handles tspSpellCheck.Click

 

    Me.SpellCheckVB1.CheckSpelling()

    Me.Refresh()
End Sub 

 

The next section of code in the demo project is used to save the contents of the control into a file.  There is nothing unique about how this save method works, it is based upon the use of a SaveFileDialog and relies upon the rich text box control’s Save File method if the content is rich text.  If the content is not rich text, it will be saved using the alternative method provided.

  

Private Sub tspSave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) HandlestspSave.Click

 

    Try

 

        SaveFileDialog1.Title = "Save File"

        SaveFileDialog1.DefaultExt = "rtf"

        SaveFileDialog1.Filter = "Rich Text Files|*.rtf|Text

        Files|*.txt|HTML Files|*.htm|All Files|*.*"

        SaveFileDialog1.FilterIndex = 1

 

        If SaveFileDialog1.ShowDialog() = DialogResult.OK Then

 

            If SaveFileDialog1.FileName = "" Then

                Return

            End If

 

            Dim strExt As String

            strExt = System.IO.Path.GetExtension(SaveFileDialog1.FileName)

            strExt = strExt.ToUpper()

 

            If strExt = ".RTF" Then

                SpellCheckVB1.SaveFile(SaveFileDialog1.FileName,

                RichTextBoxStreamType.RichText)

 

            Else

 

                Dim txtWriter As System.IO.StreamWriter

                txtWriter = New

                System.IO.StreamWriter(SaveFileDialog1.FileName)

                txtWriter.Write(SpellCheckVB1.Text)

                txtWriter.Close()

                txtWriter = Nothing

                SpellCheckVB1.SelectionStart = 0

                SpellCheckVB1.SelectionLength = 0

 

            End If

 

            currentFile = SaveFileDialog1.FileName

            SpellCheckVB1.Modified = False

            MessageBox.Show(currentFile.ToString() + " saved.""File Save")

 

            Else

 

             MessageBox.Show("Save File request cancelled by user.""Cancelled")

 

        End If

 

 

        Catch ex As Exception

             MessageBox.Show(ex.Message.ToString(), "Error")

 

    End Try

End Sub 

 

Following the Save button's click event handler, the piece of code is used to open a file into the rich text box control.  This operation is supported through the use of an open file dialog control.

 

 

Private Sub tspOpen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) HandlestspOpen.Click

 

    Try

 

        OpenFileDialog1.Title = "Open File"

        OpenFileDialog1.DefaultExt = "rtf"

        OpenFileDialog1.Filter = "Rich Text Files|*.rtf|TextFiles|*.txt|HTML Files|*.htm|All Files|*.*"

        OpenFileDialog1.FilterIndex = 1

        OpenFileDialog1.FileName = String.Empty

 

        If OpenFileDialog1.ShowDialog() = DialogResult.OK Then

 

            If OpenFileDialog1.FileName = "" Then

 

                Return

 

            End If

 

            Dim strExt As String

            strExt =

            System.IO.Path.GetExtension(OpenFileDialog1.FileName)

            strExt = strExt.ToUpper()

 

            If strExt = ".RTF" Then

 

                SpellCheckVB1.LoadFile(OpenFileDialog1.FileName,

                RichTextBoxStreamType.RichText)

 

            Else

 

                Dim txtReader As System.IO.StreamReader

                txtReader = New

                System.IO.StreamReader(OpenFileDialog1.FileName)

                SpellCheckVB1.Text = txtReader.ReadToEnd()

                txtReader.Close()

                txtReader = Nothing

                SpellCheckVB1.SelectionStart = 0

                SpellCheckVB1.SelectionLength = 0

 

            End If

 

            currentFile = OpenFileDialog1.FileName

            SpellCheckVB1.Modified = False

 

            Else

 

                MessageBox.Show("Open File request cancelled by user.","Cancelled")

            End If

 

    Catch ex As Exception

 

        MessageBox.Show(ex.Message.ToString(), "Error")

 

    End Try

 

End Sub 

 

The last bit of code in the demo is used to close the current form and terminate the application. 

       

Private Sub tspExit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) HandlestspExit.Click

     

    Me.Dispose()

 

End Sub

 

That wraps up the discussion of the form based demo project.

 

The Code:  Spell Check Control

The Spell Check control is a custom control built to extend the standard Windows Forms Rich Text Box control; the only additions made to the standard control were to add those items necessary to implement the Word DLL spell check method against the rich text box control. The control also exposes a couple of properties used to configure the spell check control and to define part of the spell check dialog available functionality.

If you open the code up and examine the imports, you will note following imports prior to the namespace and class declaration. 

Imports System

Imports System.Collections.Generic

Imports System.ComponentModel

Imports System.Data

Imports System.Drawing

Imports System.Text

Imports System.Windows.Forms

Imports Microsoft.Office.Core

Imports Microsoft.Office.Interop.Word 

 

Public Class SpellCheckVB

    Inherits System.Windows.Forms.RichTextBox

After the class declaration; the code defines a region containing a collection of member variables used to support setting the control’s properties and to configure the arguments passed to the check spelling function exposed by the Word.DLL; note that these variables are declared as objects; this is essential to working with the Word.DLL exposed check spelling argument list where all arguments are passed by reference as objects. 

#Region "Member Variables"
 

    Private emptyItem As Object = System.Reflection.Missing.Value

    Private oNothing As Object = Nothing

    Private oTrue As Object = True

    Private oFalse As Object = False

    Private oAlwaysSuggest As Object = True

    Private oIgnoreUpperCase As Object = False

    Private mAlwaysSuggest As Boolean = True

    Private mIgnoreUpperCase As Boolean = False

 

#End Region 
 

The control exposes two public properties, one is used to set the Word.DLL spell check method’s Always Suggest option, and the other is used to set its Ignore Upper Case option.  In order work effectively in the IDE as design time; the type is set as a Boolean (both properties) but when the Boolean is set, a shadowing object is also set to equal true or false; it is the object and not the Boolean that is actually passed to the Word.DLL check spelling method.

The Word.DLL check spelling method would also permit the user to pass custom dictionaries to it through additional arguments; in this example, I did not expose any properties to include any custom dictionaries however, using the same approach, one could pass in these alternative custom dictionaries. 

#Region "Properties"

 

    Public Property AlwaysSuggest() As Boolean

        Get

            Return mAlwaysSuggest

        End Get

        Set(ByVal value As Boolean)

            mAlwaysSuggest = value

 

            If mAlwaysSuggest = True Then

                oAlwaysSuggest = True

            Else

                oAlwaysSuggest = False

            End If

        End Set

    End Property 

 

    Public Property IgnoreUpperCase() As Boolean

        Get

            Return mIgnoreUpperCase

        End Get

        Set(ByVal value As Boolean)

            mIgnoreUpperCase = value

 

            If mIgnoreUpperCase = True Then

                oIgnoreUpperCase = True

            Else

                oIgnoreUpperCase = False

            End If

        End Set

    End Property 

 

#End Region
 

The following code covers the control’s default constructor and On Paint method:

#Region "Constructor and Defaults"
 

    Public Sub New()

 

        InitializeComponent()

 

    End Sub 

 

    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)

 

        MyBase.OnPaint(e) 

        'Add your custom paint code here
 

    End Sub

 

#End Region

The next bit of code is that which is required to perform the actual spell check function based upon the use of the Word.DLL.  This section of code is annotated to describe the content.

       

#Region "Perform Spell Check" 

 

    ''' <summary>

    ''' Perform spell check operation on control content.

    ''' This operation displays the results of the spell

    ''' check. 

    '''

    ''' Alternatively, the function could be set to return

    ''' a string and the results string could be returned

    ''' to the caller

    ''' </summary>
 

    Public Sub CheckSpelling()

 

        ' declare local variables to track error count

        ' and information

        Dim SpellingErrors As Integer = 0

        Dim ErrorCountMessage As String = String.Empty

 

        ' create an instance of a word application

        Dim WordApp As Microsoft.Office.Interop.Word.Application =  _ NewMicrosoft.Office.Interop.Word.Application()

 

        ' hide the MS Word document during the spellcheck

        WordApp.Visible = False

        WordApp.ShowWindowsInTaskbar = False

 

        ' check for zero length content in text area

        If Me.Text.Length > 0 Then

 

            ' create an instance of a word document

            Dim WordDoc As _Document =  WordApp.Documents.Add(emptyItem, _ emptyItem, _emptyItem, _ oFalse)

 

            ' load the content written into the word doc

            WordDoc.Words.First.InsertBefore(Me.Text)

 

            ' collect errors form new temporary document set to contain

            ' the content of this control

            Dim docErrors As Microsoft.Office.Interop.Word.ProofreadingErrors

            = WordDoc.SpellingErrors

            SpellingErrors = docErrors.Count

 

            ' execute spell check; assumes no custom dictionaries

            WordDoc.CheckSpelling(oNothing, oIgnoreUpperCase, oAlwaysSuggest,

                oNothing, oNothing, oNothing, oNothing, oNothing, _

                oNothing, oNothing, oNothing, oNothing)

 

            ' format a string to contain a report of the errors detected

            ErrorCountMessage = "Spell check complete; errors detected: " +

            SpellingErrors.ToString()

 

            ' return corrected text to control's text area

            Dim first As Object = 0

            Dim last As Object = WordDoc.Characters.Count - 1

            Me.Text = WordDoc.Range(first, last).Text

 

        Else

 

            ' if nothing was typed into the control, abort and inform user

            ErrorCountMessage = "Unable to spell check an empty text box."

 

 

            WordApp.Quit(oFalse, emptyItem, emptyItem)

 

            ' return report on errors corrected

            ' - could either display from the control or change this to

            ' - return a string which the caller could use as desired.

            MessageBox.Show(ErrorCountMessage, "Finished Spelling Check")

 

        End If

 

    End Sub

 

#End Region

End Class
 

At design time, the control user may set properties in the property grid, or the values may be set in the code.

properties-in-vb.net.jpg
Figure 3:  Property for "Always Suggest" Option

Summary

This article described an approach to creating a text input control capable of checking the spelling contained in the text area of the control. The control is an extended version of the rich text box control and relies upon the Word.DLL check spelling function in order to support internal spell checking.  The control may be useful if one were capturing free text entries from a user  and it was deemed desirable to check the content of those free text entries for misspellings.

Next Recommended Readings