Introduction
This article describes an easy approach to building a
simple word processor around an extended version of the Rich Text Box (RTB)
control; Microsoft has made available an extended version of the RTB control
that greatly eases the requirements for printing the control's 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 RTB's content
- Adding Bullets to sections of an RTB's 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.
Figure 1: The Editor Application in Use
Getting Started:
In order to get started, unzip the attachment and load
the solution into Visual Studio 2005. Examine the solution explorer and note
the files contained in the project:
Figure 2: The Solution Explorer Showing the Project
Files
First note that there are two separate projects
contained in the solution. The first project is a class library entitled,
"ExtendedRichTextBox", that library contains a single control class,
"RichTextBoxPrintCtrl.vb". This control class was provided by Microsoft as an
alternative to the basic Rich Text Box control; the class inherits from the
RichTextBox control class but adds to that base class additional support for
printing the control's content. The approach provided by the control is far
simpler than the traditional approach used as based upon the manipulation of the
graphic context of the control.
The second solution is the editor application itself
(RichTextEditor). This application uses the extended rich text box control and
then to that adds in all of the normal document manipulation techniques (such as
font selection, indentation, and file IO support). Aside from the main
application's form (frmMain.vb), this project also includes two additional
forms, one to search for a string within the RTB's content, and one to search
for and replace strings within the RTB. These forms are frmFind.vb and
frmReplace.vb.
Figure 3: Editor Application Find Dialog
Figure 4: Editor Application Find and Replace Dialog
In addition to the form classes mentioned, the solution
also contains a folder entitled, "Graphics"; this folder contains all of the
image files used to support the application's menus and toolbar.
Project References.
Aside from the default references, there are a couple
of additional references added. Most notably, the extended rich text box
control library is added to allow for the use of the extended rich text box
control. Figure 2 shows the references as they exist in the project.
Figure 5: Project References
The Code: Main Form Class.
The main form class (frmMain.vb) is pretty easy to
follow. It begins with a couple of import statements followed by the class
declaration. The code is divided by purpose into four separate regions which
are:
- Declarations
- Menu Methods
- Toolbar Methods
- Printing
The imports and class declaration sections of code looks like this:
Imports
System.Drawing
Imports
System.Drawing.Image
Public
Class frmMain
The class declaration is plain enough and does not
inherit from or implement any base class or interface. I would emphasis here
again that making use of Microsoft's extended rich text box control greater
reduces the amount of code necessary to support all of the methods used within
this application.
The declarations section is also very simple; the
section contains both of the variables used throughout the application. The
content is as follows:
#Region
"Declarations"
Private currentFile
As String
Private checkPrint As
Integer
#End
Region
The
"currentFile" variable is used to keep track of the path and file name of the
file loaded into the extended rich text box control; it is updated whenever the
user opens a file, creates and saves a file, or saves a file with a new name
and/or file extension.
The
"checkPrint" variable is used by the streamlined printing process recommended by
Microsoft in the article describing the use of the extended rich text box
control. It is used to determine if additional pages exist when the document is
sent to the printer (in support of multi-page printing).
The next
section of code is the primary block of code used by this application, the "Menu
Methods" region contains all of the subroutines evoked in response to the
selection of a menu option. The "Toolbar Methods" region follows the "Menu
Methods" region, but all of the subroutines in the toolbar control section call
the subroutines defined in the "Menu Methods" region of the code unless the code
was so trivial (one line) that it was just as simple to make the call directly
as it was to call menu related subroutine; for that reason, this document will
not describe the content of the "Toolbar Methods" region specifically.
The
first block of code in the menu region is used to create a new file:
Private
Sub NewToolStripMenuItem_Click(ByVal
sender As System.Object,
ByVal
e As System.EventArgs)
Handles NewToolStripMenuItem.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.Yes
Then
rtbDoc.Clear()
Else
Exit Sub
End If
Else
rtbDoc.Clear()
End If
currentFile =
""
Me.Text = "Editor:
New Document"
End
Sub
In this
subroutine, prior to clearing the current document, the status of the current
document is checked by means using the controls "Modified" test; if the document
has been 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 loose) 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 show after user requests
new document with 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 Open File subroutine which in turn exposes a File Open dialog used to
allow the user to navigate to the file they wish to open. The Open File
subroutine is next and contains this code:
Private
Sub OpenFile()
OpenFileDialog1.Title =
"RTE - Open File"
OpenFileDialog1.DefaultExt = "rtf"
OpenFileDialog1.Filter
= "Rich Text Files|*.rtf|Text Files|*.txt|HTML
Files|*.htm|All Files|*.*"
OpenFileDialog1.FilterIndex = 1
OpenFileDialog1.ShowDialog()
If OpenFileDialog1.FileName =
"" Then
Exit Sub
Dim strExt As
String
strExt =
System.IO.Path.GetExtension(OpenFileDialog1.FileName)
strExt =
strExt.ToUpper()
Select Case
strExt
Case ".RTF"
rtbDoc.LoadFile(OpenFileDialog1.FileName,
RichTextBoxStreamType.RichText)
Case Else
Dim txtReader As
System.IO.StreamReader
txtReader =
New
System.IO.StreamReader(OpenFileDialog1.FileName)
rtbDoc.Text =
txtReader.ReadToEnd
txtReader.Close()
txtReader =
Nothing
rtbDoc.SelectionStart = 0
rtbDoc.SelectionLength = 0
End Select
currentFile =
OpenFileDialog1.FileName
rtbDoc.Modified =
False
Me.Text = "Editor:
" & currentFile.ToString()
End
Sub
Figure 7: Open File Dialog
The first part of the File Open subroutine is used to
configure and display the Open File Dialog box; this code sets up the filters
for the files types (rich text, text, or html), sets the dialog box title, and a
selects an extension filter (rtf). Once this is done, the dialog box is
displayed, if the user Okays the dialog box without specifying a file name, the
subroutine will exit. If a file name exists, the code extracts the file
extension from the file name, places the extension in a local string variable,
converts it to upper case and does a select case statement on the string
variable. If the file selected by the user is an RTF file, the subroutine calls
the control's Load File method and passes it the file name and format. If the
file is not an RTF file, a stream reader is instanced and passed the path to the
file, the control is then fed the content of the file by means of the stream
reader's read to end method. The reader is then closed and disposed of and the
cursor is moved to the beginning of the document and the selection length is set
to zero (if you do not do this, the whole document will initialize as entirely
selected). After the file is loaded, the "currentFile" variable is updated to
contain the current file path and name, the modified property of the control is
set to false, and the caption bar is updated to show the name of the file
currently under edit in the rich text box control.
The next item up is the "Save" menu option; it contains
the following code:
Private
Sub SaveToolStripMenuItem_Click(ByVal
sender As System.Object,
ByVal
e As System.EventArgs)
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 similarly
to the approach used to open the file however instead of opening a file, the
approach is used to call the rich text box control's Save File 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 extension
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:
Private
Sub SaveAsToolStripMenuItem_Click(ByVal
sender As System.Object,
ByVal
e As System.EventArgs)
Handles SaveAsToolStripMenuItem.Click
SaveFileDialog1.Title =
"RTE - Save File"
SaveFileDialog1.DefaultExt = "rtf"
SaveFileDialog1.Filter
= "Rich Text Files|*.rtf|Text Files|*.txt|HTML
Files|*.htm|All
Files|*.*"
SaveFileDialog1.FilterIndex = 1
SaveFileDialog1.ShowDialog()
If SaveFileDialog1.FileName =
"" Then
Exit Sub
Dim strExt As
String
strExt =
System.IO.Path.GetExtension(SaveFileDialog1.FileName)
strExt = strExt.ToUpper()
Select Case
strExt
Case ".RTF"
rtbDoc.SaveFile(SaveFileDialog1.FileName,
RichTextBoxStreamType.RichText)
Case Else
Dim txtWriter As
System.IO.StreamWriter
txtWriter =
New
System.IO.StreamWriter(SaveFileDialog1.FileName)
txtWriter.Write(rtbDoc.Text)
txtWriter.Close()
txtWriter =
Nothing
rtbDoc.SelectionStart = 0
rtbDoc.SelectionLength = 0
End Select
currentFile =
SaveFileDialog1.FileName
rtbDoc.Modified =
False
Me.Text = "Editor:
" & currentFile.ToString()
End
Sub
Figure 8: File Menu Options
By now this should look pretty familiar; in the code, a
save as file dialog box is configured and displayed to the user. The dialog
will permit the user to save the file as rtf, txt, or html. If the user saves
the file as rtf, the control's save file method is used to store the contents of
the file whilst preserving the rtf formatting. If the user selects another
option, the file will be saved as plain text using a text writer. In either
case, after the file is saved, the "currentFile" variable is updated, the
application's title bar is updated, and the document's modified property is set
to false.
The next item in the code is the menu's Exit call. It
is used to terminate the application. Prior to closing the application, this
subroutine checks to see if the current document has been modified and, if it
has, it alerts the user and asks whether or not the document should be saved
prior to closing it and the application. The code is as follows:
Private
Sub ExitToolStripMenuItem_Click(ByVal
sender As System.Object,
ByVal
e As System.EventArgs)
Handles ExitToolStripMenuItem.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
Application.Exit()
End If
Else
Application.Exit()
End If
End
Sub
The next menu option addressed is the edit menu's
"Select All" function. Select All is a method embedded in the rich text box
control and therefore it may be called directly without writing any additional
code to make the select all happen; to use it, just call it as follows:
Private
Sub SelectAllToolStripMenuItem_Click(ByVal
sender As System.Object,
ByVal e As
System.EventArgs) Handles
SelectAllToolStripMenuItem.Click
Try
rtbDoc.SelectAll()
Catch exc As
Exception
MessageBox.Show("Unable to select all document
content.", "RTE-
Select",
MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
End
Sub
Following the edit menu's "Select All" function, we have
the cut, copy, and paste subroutines. Just as the Select All method exists
within the rich text box control, so do these and so you can call them directly
in a manner similar to that used in Select All, for that reason, I am not going
to show them here but you can see the calls made in the example application if
you'd care to take a look at them.
Figure 9: Edit Menu Options
Next up is the menu option used to select the current
font. This code merely uses a standard font dialog box to set the rich text box
control's selection font property to the font selected by the user through the
font dialog. The code used to do this is as follows:
Private
Sub SelectFontToolStripMenuItem_Click(ByVal
sender As
System.Object,
ByVal e As
System.EventArgs) Handles
SelectFontToolStripMenuItem.Click
If Not
rtbDoc.SelectionFont Is
Nothing Then
FontDialog1.Font = rtbDoc.SelectionFont
Else
FontDialog1.Font = Nothing
End If
FontDialog1.ShowApply =
True
If FontDialog1.ShowDialog() =
Windows.Forms.DialogResult.OK Then
rtbDoc.SelectionFont = FontDialog1.Font
End If
End
Sub
Figure 10: Font Dialog in Use
Similarly the font color menu option is used to display
a standard color dialog to the user; if the user selects a color from the
dialog, the fore color property of the document will be updated to contain the
selected color. As the rich text box control works primarily with selected text
(that is, what you change in terms of selecting a font or changing a color),
this function will alter the color only of the selected text. If no text is
selected, the color at the insertion point will hold the fore color selection
and typing from the insertion point will show text in the newly selected color.
Private
Sub FontColorToolStripMenuItem_Click(ByVal
sender As
System.Object,
ByVal e As
System.EventArgs) Handles
FontColorToolStripMenuItem.Click
ColorDialog1.Color =
rtbDoc.ForeColor
If ColorDialog1.ShowDialog =
Windows.Forms.DialogResult.OK Then
rtbDoc.SelectionColor = ColorDialog1.Color
End If
End
Sub
The next three sections of code are the subroutines used
to set the selected text's bold, italic, or underline properties. Each section
is set up to work such that, if the selected text is bold, selecting the bold
option will remove the bolding (or italics, or underline). (As they all
basically work the same, I am only showing bold here)
Private
Sub BoldToolStripMenuItem_Click(ByVal
sender As System.Object,
ByVal e As
System.EventArgs) Handles
BoldToolStripMenuItem.Click
If Not
rtbDoc.SelectionFont Is
Nothing Then
Dim currentFont As
System.Drawing.Font = rtbDoc.SelectionFont
Dim newFontStyle As
System.Drawing.FontStyle
If rtbDoc.SelectionFont.Bold =
True Then
newFontStyle =
FontStyle.Regular
Else
newFontStyle =
FontStyle.Bold
End If
rtbDoc.SelectionFont = New
Font(currentFont.FontFamily,
currentFont.Size,
newFontStyle)
End If
End
Sub
The "Normal" font menu option returns the selected text
to a normal, unadorned format:
Private
Sub NormalToolStripMenuItem_Click(ByVal
sender As System.Object,
ByVal e As
System.EventArgs) Handles
NormalToolStripMenuItem.Click
If Not
rtbDoc.SelectionFont Is
Nothing Then
Dim currentFont As
System.Drawing.Font = rtbDoc.SelectionFont
Dim newFontStyle As
System.Drawing.FontStyle
newFontStyle =
FontStyle.Regular
rtbDoc.SelectionFont = New
Font(currentFont.FontFamily,
currentFont.Size,
newFontStyle)
End If
End
Sub
The menu option used to set the page color is used to
expose a color dialog box to the user; if the user selects a color form the
dialog, the back color of the rich text box control is set to that color. The
code to support this function is as follows:
Private
Sub PageColorToolStripMenuItem_Click(ByVal
sender As
System.Object,
ByVal e As
System.EventArgs) Handles
PageColorToolStripMenuItem.Click
ColorDialog1.Color
= rtbDoc.BackColor
If ColorDialog1.ShowDialog =
Windows.Forms.DialogResult.OK Then
rtbDoc.BackColor =
ColorDialog1.Color
End If
End
Sub
Figure 11: Color Dialog in Use
The undo and redo functions are used to back up or
restore changes made to the content of the control during an edit; the rich text
box control supports the undo and redo function directly so all you need to do
in order to add undo and redo support is merely evoke the method directly from
the control, to make the call, test to determine whether or not the control can
execute the undo or redo request, and, if it is supported, call the method:
Private
Sub mnuUndo_Click(ByVal
sender As System.Object,
ByVal e As
System.EventArgs) Handles mnuUndo.Click
If rtbDoc.CanUndo
Then rtbDoc.Undo()
End
Sub
Private
Sub mnuRedo_Click(ByVal
sender As System.Object,
ByVal e As
System.EventArgs)
Handles mnuRedo.Click
If rtbDoc.CanRedo
Then rtbDoc.Redo()
End
Sub
The next three sections of code address setting the
document's horizontal alignment property to support left, centered, or right
justification of the selected text. Each of these alignment control options is
directly supported by the control:
Private
Sub LeftToolStripMenuItem_Click_1(ByVal
sender As System.Object,
ByVal e As
System.EventArgs) Handles
LeftToolStripMenuItem.Click
rtbDoc.SelectionAlignment = HorizontalAlignment.Left
End
Sub
Private
Sub CenterToolStripMenuItem_Click_1(ByVal
sender As
System.Object,
ByVal e As
System.EventArgs) Handles
CenterToolStripMenuItem.Click
rtbDoc.SelectionAlignment = HorizontalAlignment.Center
End
Sub
Private
Sub RightToolStripMenuItem_Click_1(ByVal
sender As System.Object,
ByVal e As
System.EventArgs) Handles
RightToolStripMenuItem.Click
rtbDoc.SelectionAlignment = HorizontalAlignment.Right
End
Sub
Figure 12: Alignment Options
Adding and removing bullets is also directly supported
by the control, the Bullet Indent property sets the gap between the bullet and
the text, the Selection Bullet property merely instructs the control to add or
remove the bullet from the selected text:
Private
Sub AddBulletsToolStripMenuItem_Click(ByVal
sender As
System.Object,
ByVal e As
System.EventArgs) Handles
AddBulletsToolStripMenuItem.Click
rtbDoc.BulletIndent =
10
rtbDoc.SelectionBullet
= True
End
Sub
Private
Sub RemoveBulletsToolStripMenuItem_Click(ByVal
sender As
System.Object,
ByVal e As
System.EventArgs) Handles
RemoveBulletsToolStripMenuItem.Click
rtbDoc.SelectionBullet
= False
End
Sub
Figure 13: Bullet Options
Setting the indentation level for the selected text is
also directly supported by the control:
Private
Sub mnuIndent0_Click(ByVal
sender As System.Object,
ByVal e As
System.EventArgs)
Handles mnuIndent0.Click
rtbDoc.SelectionIndent
= 0
End
Sub
Figure 14: Indentation Options
The application contains a separate dialog box used to
find a text string within the current document, if the user selects the find
menu option, the application will create and display a new instance of the
search form (frmFind.vb):
Private
Sub FindToolStripMenuItem_Click(ByVal
sender As System.Object,
ByVal
e As System.EventArgs)
Handles FindToolStripMenuItem.Click
Dim f As
New frmFind()
f.Show()
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 content of the
current rich text box control as the print document; 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 a open file dialog box set to filter for 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
Figure 15: Embedding an Image File
Once the user selects a file through the open file
dialog, the subroutine will create an image using the Image.FromFile method.
This image is then placed into the clipboard and subsequently pasted into the
document.
The last section of the main form's code is contained
in the printing region. The calls used to print, due to the use of the extended
rich text box control are very simple:
Private
Sub PrintDocument1_BeginPrint(ByVal
sender As Object,
ByVal e As
System.Drawing.Printing.PrintEventArgs) Handles
PrintDocument1.BeginPrint
' Adapted from Microsoft's example for extended
richtextbox control
'
checkPrint = 0
End
Sub
The Begin Print subroutine is used to set the "checkPrint"
variable back to zero at the start of each new print job.
The Print Page subroutine evokes the extended rich text
box control's print method to send the entire or selected section of the current
document to the printer. The call also checks to see if more than a single page
exists and it will continue to print until all of the pages have been passed to
the printer. The code used to print is as follows:
Private
Sub PrintDocument1_PrintPage(ByVal
sender As Object,
ByVal e As
System.Drawing.Printing.PrintPageEventArgs) Handles
PrintDocument1.PrintPage
' Adapted from Microsoft's example for extended
richtextbox control
'
' Print the content of the RichTextBox. Store the
last character
printed.
checkPrint =
rtbDoc.Print(checkPrint, rtbDoc.TextLength, e)
' Look for more pages
If checkPrint < rtbDoc.TextLength
Then
e.HasMorePages =
True
Else
e.HasMorePages =
False
End If
End
Sub
Figure 16: Print Preview
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.vb class. The find class is defined in frmFind.vb 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 straight forward, 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 by from the InStr call; InStr is passed the
starting position of 1, the entire body of 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 replaces 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
If frmMain.rtbDoc.SelectedText.Length <> 0
Then
frmMain.rtbDoc.SelectedText = txtReplacementText.Text
End If
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 all function is a little different in that
it uses a the replace method to replace every instance of the search term with
the replacement term throughout the entire body of text:
Private
Sub btnReplaceAll_Click(ByVal
sender As System.Object,
ByVal e As
System.EventArgs)
Handles btnReplaceAll.Click
Dim currentPosition
As Integer =
frmMain.rtbDoc.SelectionStart
Dim currentSelect As
Integer = frmMain.rtbDoc.SelectionLength
frmMain.rtbDoc.Rtf =
Replace(frmMain.rtbDoc.Rtf,
Trim(txtSearchTerm.Text), Trim(txtReplacementText.Text))
frmMain.rtbDoc.SelectionStart = currentPosition
frmMain.rtbDoc.SelectionLength = currentSelect
frmMain.Focus()
End
Sub
Again, the frmFind.vb 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.vb class was developed at Microsoft; for a complete
description of the content of the class, please refer to this link in you Visual
Studio 2005 help files:
MS-HELP://MS.VSCC.V80/MS.MSDN.V80/MS.KB.V10.EN/ENU_KBVBNETKB/VBNETKB/811401.HTM
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 rich text box 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 the text or rich
text file. Further, the application provided an approach to inserting an image
into the rich text box as a means of creating a more useful application based
upon the rich text box control.