Building A Simple Word Processor Around An Extended RichTextBox Control
Building A Simple Word Processor Around An Extended RichTextBox Control
RichTextBox Control
Introduction
This article describes an easy approach to building a simple word processor around an
extended version of the RichTextBox (RTB) control. Microsoft has made available an
extended version of the RTB control that greatly eases the requirements for printing the
controls text or RTF content. This article and the sample application will use this
extended version of the RTF control to demonstrate the following word processor related
functions:
Opening Text, RTF, HTML, or other text files into a RTB control
Saving Text, RTF, HTML, or other text files from an RTB control
Implementation of the Page Setup dialog control
Implementation of the Print Preview dialog control
Implementation of the Print dialog control
Setting font properties on selected text or RTF within the RTB control
Searching for and highlighting text contained within the RTB control
Searching for and replacing text contained within the RTB control
Adding indentation to sections of an RTBs content
Adding bullets to sections of an RTBs content
Implementing Undo/Redo within an RTB
Implementing Select All, Cut, Copy, and Paste in an RTB control
Embedding images into an RTB control
Setting page and font colors
Implementing alignment options in an RTB control
Whilst this project will not lead you to drop MS Word, it is a decent little word processor,
and to that end, you may find a use for it. I have always kept one of these on hand, and
have frequently tailored them to do things like provide a custom tool for viewing reports,
error logs, and things of that nature when I wanted to integrate that feature into a product
so that I could use it in lieu of doing something like shelling out a text file into Notepad.
Doing so allows me to control the appearance of the application, the caption in the title
bar of the form, etc.
modified while it has been open, the test will return true. If the document has been
modified, the user is queried with a message box to determine whether or not they want
to save (or lose) the modifications made to the current file prior to clearing the file. If
they choose to save the changes, the subroutine is exited; else, the document is cleared,
and the changes are lost. If the document has not been modified, the subroutine will clear
the document without notifying the user. Whenever the document is cleared, the title of
the control is updated to indicate that a new (unsaved) document is the current document,
and the currentFile variable is set to contain an empty string.
Figure 6: Confirmation dialog shown after user requests a new document without saving
changes
The next subroutine is used to open an existing file into the rich text box control:
Private Sub OpenToolStripMenuItem_Click(ByVal sender _
As System.Object, ByVal e As System.EventArgs) _
Handles OpenToolStripMenuItem.Click
If rtbDoc.Modified Then
Dim answer As Integer
answer = MessageBox.Show("The current document has not" & _
" been saved, would you like to continue " & _
"without saving?", "Unsaved Document", _
MessageBoxButtons.YesNo, MessageBoxIcon.Question)
If answer = Windows.Forms.DialogResult.No Then
Exit Sub
Else
OpenFile()
End If
Else
OpenFile()
End If
End Sub
This subroutine works in a manner similar to the new subroutine discussed in the
previous section. If the file has not been modified or if the user decides not to save the
current modifications, the subroutine calls an OpenFile subroutine, which in turn exposes
a File Open dialog used to allow the user to navigate to the file they wish to open. The
OpenFile subroutine is next, and contains this code:
Handles SaveToolStripMenuItem.Click
If currentFile = "" Then
SaveAsToolStripMenuItem_Click(Me, e)
Exit Sub
End If
Dim strExt As String
strExt = System.IO.Path.GetExtension(currentFile)
strExt = strExt.ToUpper()
Select Case strExt
Case ".RTF"
rtbDoc.SaveFile(currentFile)
Case Else
' to save as plain text
Dim txtWriter As System.IO.StreamWriter
txtWriter = New System.IO.StreamWriter(currentFile)
txtWriter.Write(rtbDoc.Text)
txtWriter.Close()
txtWriter = Nothing
rtbDoc.SelectionStart = 0
rtbDoc.SelectionLength = 0
rtbDoc.Modified = False
End Select
Me.Text = "Editor: " & currentFile.ToString()
End Sub
The Save function first checks to see if the currentFile variable is empty; if it
is, the content of the rich text box control has not been saved previously, and the
subroutine will call the Save As menu option to provide the user with an interface to
define a file name and storage location for the current unnamed file. If the file is named
(and has a current storage location), the subroutine will check the file extension and, by
means of a Select Case statement, determine the appropriate method for storing the file,
and will then save the content to the file location. This all works very similar to the
approach used to open the file. However, instead of opening a file, the approach is used to
call the rich text box controls SaveFile method if the file is a rich text file, or to
instance a stream writer and write the file content out as text to the file location if the file
is plain text or HTML.
With both the file open and file save methods used, if the file is anything other than a rich
text file, the application will attempt to open or save it with a stream reader or stream
writer; this will allow the application to work with any text file, not just RTF, TXT, or
HTML files. That would permit you to use it with custom file types, or other things such
as license files or error log files.
The next subroutine addresses the Save As menu option; its code is as follows:
End Sub
Similarly, if the user selects the Find and Replace menu option, the application will create
and display a new instance of the find and replace form (frmReplace.vb):
Private Sub FindAndReplaceToolStripMenuItem_Click(ByVal sender _
As System.Object, ByVal e As System.EventArgs) _
Handles FindAndReplaceToolStripMenuItem.Click
Dim f As New frmReplace()
f.Show()
End Sub
The print document is set to contain the contents of the current rich text box control. In
order to support print preview, page setup, and printing, given the modifications made to
the extended rich text box control, all that needs to be done is to pass the print document
to each of the related standard dialog boxes:
Private Sub PreviewToolStripMenuItem_Click(ByVal sender _
As System.Object, ByVal e As System.EventArgs) _
Handles PreviewToolStripMenuItem.Click
PrintPreviewDialog1.Document = PrintDocument1
PrintPreviewDialog1.ShowDialog()
End Sub
Private Sub PrintToolStripMenuItem_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles PrintToolStripMenuItem.Click
PrintDialog1.Document = PrintDocument1
If PrintDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then
PrintDocument1.Print()
End If
End Sub
Private Sub mnuPageSetup_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles mnuPageSetup.Click
PageSetupDialog1.Document = PrintDocument1
PageSetupDialog1.ShowDialog()
End Sub
The next subroutine is a little more interesting; it is used to embed an image file into the
extended rich text box document. This subroutine uses an open file dialog box set to filter
the extensions used for bitmaps, JPEGs, and GIF files. The user may navigate to the file
that they want to embed into the document (placing it at the insertion point defined by the
cursor).
Private Sub InsertImageToolStripMenuItem_Click(ByVal sender _
As System.Object, ByVal e As System.EventArgs) _
Handles InsertImageToolStripMenuItem.Click
OpenFileDialog1.Title = "RTE - Insert Image File"
OpenFileDialog1.DefaultExt = "rtf"
OpenFileDialog1.Filter = "Bitmap Files|*.bmp|JPEG Files|*.jpg|GIF
Files|*.gif"
OpenFileDialog1.FilterIndex = 1
OpenFileDialog1.ShowDialog()
If OpenFileDialog1.FileName = "" Then Exit Sub
Try
Dim strImagePath As String = OpenFileDialog1.FileName
Dim img As Image
img = Image.FromFile(strImagePath)
Clipboard.SetDataObject(img)
Dim df As DataFormats.Format
df = DataFormats.GetFormat(DataFormats.Bitmap)
If Me.rtbDoc.CanPaste(df) Then
Me.rtbDoc.Paste(df)
End If
Catch ex As Exception
MessageBox.Show("Unable to insert image format selected.", "RTE
Paste", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
End Sub
The print section wraps up the rest of the main form class.
Code: The Find and Replace Form
The find and replace form is supported with the frmReplace class. The find class is
defined in frmFind, but since it contains two subroutines (Find and Find Next) which are
also contained in the Find and Replace form, I will only discuss the code contained in the
Find and Replace form.
The Find and Replace form supports four subroutines:
Find
Find Next
Replace
Replace All
The Find subroutine is pretty straightforward, it will search the entire document for the
first occurrence of the search term defined by the user on the form. It will search in one
of two ways: with or without matching the case of the search term. Depending upon
whether or not the user has checked the Match Case check box on the form, the
application will search for the text using either the binary or text compare method. With
the binary method, the search term must match exactly (including case); with the text
compare method, the strings just need to match. The StartPosition integer value is
set to the value returned from the InStr call; InStr is passed the starting position of 1, the
entire body of the text contained in the rich text box control (as the article to search), the
search term entered by the user, and the search compare method. InStr will return the
index position of the found text if the text is in fact found. If nothing is found, it will
return a zero. If the starting position value is zero, the user will be notified that the search
term was not found, else, the application will highlight the found text in the document,
pan to its location, and set the focus back to the main form (which in turn makes the
highlighting visible to the user).
Private Sub btnFind_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnFind.Click
Dim StartPosition As Integer
Dim SearchType As CompareMethod
If chkMatchCase.Checked = True Then
SearchType = CompareMethod.Binary
Else
SearchType = CompareMethod.Text
End If
StartPosition = InStr(1, frmMain.rtbDoc.Text, _
txtSearchTerm.Text, SearchType)
If StartPosition = 0 Then
MessageBox.Show("String: '" & txtSearchTerm.Text.ToString() & _
"' not found", "No Matches", _
MessageBoxButtons.OK, MessageBoxIcon.Asterisk)
Exit Sub
End If
frmMain.rtbDoc.Select(StartPosition - 1, txtSearchTerm.Text.Length)
frmMain.rtbDoc.ScrollToCaret()
frmMain.Focus()
End Sub
The Find Next function works in a manner consistent with the Find function; the only
difference is that it sets the start position to the current position of the selection starting
point within the document so that the Find Next function will not start at the beginning of
the document each time it searches:
Private Sub btnFindNext_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnFindNext.Click
Dim StartPosition As Integer = frmMain.rtbDoc.SelectionStart + 2
Dim SearchType As CompareMethod
If chkMatchCase.Checked = True Then
SearchType = CompareMethod.Binary
Else
SearchType = CompareMethod.Text
End If
StartPosition = InStr(StartPosition, frmMain.rtbDoc.Text, _
txtSearchTerm.Text, SearchType)
If StartPosition = 0 Then
MessageBox.Show("String: '" & txtSearchTerm.Text.ToString() & _
"' not found", "No Matches", _
MessageBoxButtons.OK, MessageBoxIcon.Asterisk)
Exit Sub
End If
frmMain.rtbDoc.Select(StartPosition - 1, txtSearchTerm.Text.Length)
frmMain.rtbDoc.ScrollToCaret()
frmMain.Focus()
End Sub
The Replace subroutine is quite simple. It merely tests to see if any text is selected and, if
it is, it is replaced with the replacement text entered into the form by the user; it then
moves to the next occurrence of the search term if one exists:
Private Sub btnReplace_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnReplace.Click
End Sub
Again, the frmFind class is the same as the Replace class with the exception being that it
does not support the Replace and Replace All methods.
Code: Rich Text Box Print Control
The code in the class library contained in the RichTextBoxPrintCtrl class was developed
at Microsoft; for a complete description of the contents of the class, please refer to this
link in your Visual Studio 2005 Help files.
Summary
This article and sample application have attempted to demonstrate some of the available
techniques useful in creating and managing text and text files through the use of the
RichTextBox control. The control itself was modified using an approach recommended
by Microsoft to greatly facilitate the ease with which one may print the contents of a text
or rich text file. Further, the application provides an approach to inserting an image into a
RichTextBox as a means of creating a more useful application based upon the
RichTextBox control.
License
This article has no explicit license attached to it but may contain usage terms in the article
text or the download files themselves. If in doubt please contact the author via the
discussion board below.
A list of licenses authors might use can be found here