Imports System.Drawing
Imports System.Windows.Forms
Module Exercise
Public Class Starter
Inherits Form
Private txtMemo As TextBox
Dim components As System.ComponentModel.Container
Public Sub New()
InitializeComponent()
End Sub
Public Sub InitializeComponent()
Text = "Memorandum"
txtMemo = New TextBox
txtMemo.Location = New Point(10, 10)
txtMemo.Width = Width - 30
txtMemo.Height = Height - 50
txtMemo.Anchor = AnchorStyles.Left Or _
AnchorStyles.Top Or _
AnchorStyles.Right Or _
AnchorStyles.Bottom
txtMemo.Multiline = True
Controls.Add(txtMemo)
End Sub
End Class
Function Main() As Integer
Dim frmStart As Starter = New Starter
Application.Run(frmStart)
Return 0
End Function
End Module
This would produce:

|
Characteristics of a Multi-Line Text Box |
|
The multi-line text box shares all of the properties of the
single-line text box. These include the read-only attribute, the character
casing, and the password options. Although these properties are valid, some of
them may not be suitable for a multi-line text box, such as applying a password
character to hide the text, trying to auto-complete a string while the user is
typing it, etc. This is why, in most cases, we will tend to consider the
single-line and the multiple line objects are separate controls.
By default, when you add a new text box to your form, it
appears empty. When the application comes up, the user mostly reads and/or enters text in the multi-line
text box when interacting with the control. At design time, you can set the text that would display when the
multi-line text box comes up. To enter this text, in the
Properties window, click the Lines field to reveal its ellipsis button that allows you to open the String
Collection Editor. Type the desired text and click OK. On the other hand, after
the user has entered some text or a few lines of text in the control, it holds
these lines. The lines of text of a text box are stored in an array represented
by a property named Lines. This means that, at run time, you can create an array
of lines of text and assign it to the text box. Or, to get the lines of text of
the control, you can retrieve the value of the Lines property.
When a multi-line text box opens, the compiler registers the content of the control. If the user has the ability to change the text in the control and if the user changes it, the compiler flags the control as
Modified. This allows you to take actions. You can acknowledge this by programmatically setting the
Modified property to true. If another control or some other action alters the contents of the
multi-line text box, you can make sure that this property reflects the change. You can change this programmatically as follows:
Public Sub InitializeComponent()
Text = "Memorandum"
txtMemo = New TextBox
txtMemo.Location = New Point(10, 10)
txtMemo.Width = Width - 30
txtMemo.Height = Height - 50
txtMemo.Anchor = AnchorStyles.Left Or _
AnchorStyles.Top Or _
AnchorStyles.Right Or _
AnchorStyles.Bottom
txtMemo.Multiline = True
txtMemo.Modified = True
Controls.Add(txtMemo)
End Sub
|
The Maximum Length of Text |
|
The multi-line text box allows the user to enter up to 32767
characters. If you want to limit the maximum number of characters that the user can
enter to a value lower than this, you can use the MaxLength property at design
time. You can also change this programmatically. Here is an example:
Public Sub InitializeComponent()
Text = "Memorandum"
txtMemo = New TextBox
txtMemo.Location = New Point(10, 10)
txtMemo.Width = Width - 30
txtMemo.Height = Height - 50
txtMemo.Anchor = AnchorStyles.Left Or _
AnchorStyles.Top Or _
AnchorStyles.Right Or _
AnchorStyles.Bottom
txtMemo.Multiline = True
txtMemo.Modified = True
txtMemo.MaxLength = 1020
Controls.Add(txtMemo)
End Sub
If the control will be used to enter text, the user can press Enter at the end of a line to move to the next line. This ability is controlled by the Boolean
AcceptsReturn property. By default, this property is set to False
because this control is primarily created from a normal single-line TextBox
control that has no formal action to take when the user presses Enter. If you
are creating a multi-line text box and you expect your users to perform some
type of text editing, you certainly should allow them to press Enter to move to
the next line. Therefore, in most cases, when creating a multi-line text box,
you should set its AcceptsReturn property to True. To set it programmatically, assign the desired value to the
AcceptstReturn property. Here is an example:
Public Sub InitializeComponent()
Text = "Memorandum"
txtMemo = New TextBox
txtMemo.Location = New Point(10, 10)
txtMemo.Width = Width - 30
txtMemo.Height = Height - 50
txtMemo.Anchor = AnchorStyles.Left Or _
AnchorStyles.Top Or _
AnchorStyles.Right Or _
AnchorStyles.Bottom
txtMemo.Multiline = True
txtMemo.AcceptsReturn = True
Controls.Add(txtMemo)
End Sub
The user is accustomed to pressing Tab to insert tab characters in the text. By default, when the user presses Tab when interacting with your application, the focus moves from one control to the next, following the
TabIndex values of the form. Even when using a multi-line text box to perform text editing, if the user presses Tab, the focus would switch to another control or to the form. If you want a
multi-line text box to receive focus when the user presses the Tab key, set the AcceptTab property from
False (the default), to True.
When entering text in a multi-line text box control, the characters start on the left side of the
multi-line text box and are subsequently added on the right side. The ability to align text is controlled by the
TextAlign property. For a multi-line text box control, the alignment is configured using the
HorizontalAlignment enumerator.
As the user enters text in a multi-line text box box, the compiler considers that a paragraph starts from the user typing a character until he or she presses Enter. Therefore, a paragraph could be an empty space, a character, a word, a line of text, a whole page or an entire book. Depending on the width of the
multi-line text box control, the text is incrementally added to the right side of each previous character. If the caret gets to the right border of the control, the text automatically continues to the next line, although it is still considered as one paragraph. To start a new paragraph, the user has to press Enter. The ability for the text to continue on the next line when the caret encounters the right border of the
multi-line text box is controlled by the WordWrap property whose default Boolean value is set to true. If you do not want text to wrap to the subsequent line, set the
WordWrap property to false. You can also set it programmatically as follows:
Public Sub InitializeComponent()
Text = "Memorandum"
txtMemo = New TextBox
txtMemo.Location = New Point(10, 10)
txtMemo.Width = Width - 30
txtMemo.Height = Height - 50
txtMemo.Anchor = AnchorStyles.Left Or _
AnchorStyles.Top Or _
AnchorStyles.Right Or _
AnchorStyles.Bottom
txtMemo.Multiline = True
txtMemo.AcceptsReturn = True
txtMemo.WordWrap = True
Controls.Add(txtMemo)
End Sub
When a text box has been configured to hold multiple lines and once its text
becomes too long, part of the content could become hidden. To show the hidden
part, the control should be equipped with scrollbars so the user can navigate up
and down, left and right. To support the display of scrollbars, the TextBox
class is equipped with the ScrollBars property. You can specify the
option of this property at either the design time or the run time or both.
The TextBox.ScrollBars property is based on the ScrollBars
enumeration that has four members:
- None: This is the default value and its means that the text box would not
display any scrollbar
- Vertical: This option specifies that the text box should display a
vertical scroll bar when its content becomes too long
- Horizontal: This is valid only if the WordWrap property is set to false.
In this case, the text box would display a horizontal scroll bar
- Both: This allows displaying both the vertical and the horizontal
scrollbars
|
Methods to Manage a Multi-Line Text Box |
|
The multi-line text box control is based on the TextBox class. To dynamically create a
multi-line text box, declare a TextBox variable and use its default constructor
to initialize it. The other operations the user can perform on a multi-line text box can be controlled by methods such as
Undo(), Cut(), Copy(), Paste(), Clear() or SelectAll() that we reviewed for the
text box control and they function the same.
Here is an example:
Imports System.Drawing
Imports System.Windows.Forms
Module Exercise
Public Class Starter
Inherits Form
Private txtMemo As TextBox
Friend WithEvents btnSelectAll As Button
Dim components As System.ComponentModel.Container
Public Sub New()
InitializeComponent()
End Sub
Public Sub InitializeComponent()
Text = "Memorandum"
btnSelectAll = New Button()
btnSelectAll.Location = New Point(10, 10)
btnSelectAll.Text = "Action"
Controls.Add(btnSelectAll)
txtMemo = New TextBox
txtMemo.Location = New Point(10, 43)
txtMemo.Width = Width - 30
txtMemo.Height = Height - 80
txtMemo.Anchor = AnchorStyles.Left Or _
AnchorStyles.Top Or _
AnchorStyles.Right Or _
AnchorStyles.Bottom
txtMemo.Multiline = True
txtMemo.AcceptsReturn = True
txtMemo.WordWrap = True
Controls.Add(txtMemo)
End Sub
Private Sub SelectAllClicked(ByVal sender As Object, _
ByVal e As EventArgs) _
Handles btnAction.Click
txtMemo.Undo()
End Sub
End Class
Function Main() As Integer
Dim frmStart As Starter = New Starter
Application.Run(frmStart)
Return 0
End Function
End Module
The regular text box, also referred to as the edit control
in Microsoft Windows (Win32), allows the user to enter any type of string in the
control. As we saw in the previous sections, that control can also be changed
into a multi-line memo control and allow you to create a type of Notepad
application. In some cases, you may want to exercise more control on what the
user can enter in a text box. For example, if you provide a text box for a date,
the user can still enter a person's name. If you create a text box for a
telephone number, the user may instead enter somebody's salary. To assist the
user with entering a specific value into a text box, the .NET Framework provides
the masked text box.
The masked text box allows you to configure one or more
placeholders in the field of the control so that the control can accept some
characters, must reject some characters, and/or can display some other
characters you will have put so the user cannot delete them.
|
Creating a Masked Text Box |
|
To create a masked text box, from the Common Controls
section of the Toolbox, you can click MaskedTextBox and click the form. To
programmatically create a masked text box, declare a variable of type MaskedTextBox,
use the New operator to initialize it, and add it to the Controls
collection of its container. Here is an example:
Imports System.Drawing
Imports System.Windows.Forms
Module Exercise
Public Class Starter
Inherits Form
Private txtHomePhone As MaskedTextBox
Dim components As System.ComponentModel.Container
Public Sub New()
InitializeComponent()
End Sub
Public Sub InitializeComponent()
txtHomePhone = New MaskedTextBox
Controls.Add(txtHomePhone)
End Sub
End Class
Function Main() As Integer
Dim frmStart As Starter = New Starter
Application.Run(frmStart)
Return 0
End Function
End Module
The masked text box uses the same common characteristics of
other visual control: location, size, etc.
|
Characteristics of the Masked Text Box |
|
The masked text box uses the same common characteristics of
other visual control: name, location, size, background color, border size,
anchoring, docking, font, etc. Like the regular text box, the MaskedTextBox
class is derived from TextBoxBase that provides its fundamental
properties. This means that with the masked text box, you can cut or copy text
from it, you can paste text to it, you can measure the length of its text, you
can select some part of its text from a specific position to another, or you can
select all of its text. Like the regular text box, the masked text box uses the AsciiOnly
property, which indicates whether the control should accept or allow only ASCII
characters.
The primary reason for using a masked text box is to control
short lengths of text entered into it. For this reason, you should not consider
some of the multi-line characteristics of a regular text box: word wrapping,
scroll bars, the ability to use the Tab key inside the control, etc.
Probably the most important property of a masked text box, which sets it apart from the (traditional)
text box control, is its ability to control what the user can and cannot enter in the text side. To
visually configure this text, the MaskedTextBox class is equipped with a
property named Mask. There are two main ways you can configure it:
- If you already know the mask you want to use, access the
Properties window for the control and, in the Mask field, type the right formula

- If you do not know or are not sure, in the Properties window for the
control
- Click Mask and click its ellipsis button
- On the form, click the control and, under the Properties window, click
Set Mask...

- On the form, click the control, click the arrow button on it, and
click Edit Mask...

Any of these actions would open the Input Mask dialog box:
The Input Mask dialog box provides some of the most
regularly used masks in Windows and database applications (the contents of the
Input Mask dialog box depends on the language settings of the computer on which
you are using Microsoft Visual Studio. For example, the above Input Box is
adapted for US English with the US Social Security Number and telephone format).
To use an existing mask, you can click it and click OK.
If none of the masks in the list suits you, you can create
your own. In the Input Mask dialog box, you can click <Custom>, click the masked text box,
create the format, and click OK. Or, in the Properties window for the masked
text box, you can click the Mask field and create your mask. To create a mask,
you use some characters and combine them as you see fit.
The characters you can use are:
| Character |
Used For |
Placeholder
Rule |
| 0 |
Digit |
Any single digit: 0, 1,
2, 3, 4, 5, 6, 7, 8, or 9. |
| 9 |
Digit or
Empty Space |
Any single digit can be
entered or an empty space can be left. |
| # |
Digit or
Empty Space |
Any single digit, a
"+" or a "-" sign can be entered, or an empty space
can be left. |
| L |
Letter |
Any letter in either
uppercase or lowercase MUST be entered and no empty space should be
left. Digits and other non-literals are not allowed. |
| ? |
Letter |
Any letter in either
uppercase or lowercase can be entered or an empty space can be left.
Digits and other non-literals are not allowed. |
| & |
Character |
Any letter, digit, or
symbol, or empty space can be used. If the AsciiOnly property is
True, this placeholder follows the ? behavior. |
| C |
Character |
Any letter, digit, or
symbol, or empty space can be used. If the AsciiOnly property is
True, this placeholder follows the & behavior. |
| A or a |
Letters and
Digits |
A letter (lowercase and
uppercase), a digit, or an empty space is allowed. No special
characters. If the AsciiOnly property is True, only a letter is allowed. |
| > |
Uppercase
Converter |
A letter in lowercase
entered in this placeholder, and any letter in lowercase entered on the
right side of this placeholder until the next < or I character, will
be converted to uppercase. If the letter is entered in uppercase,
nothing would happen. |
| < |
Lowercase
Converter |
A letter in uppercase
entered in this placeholder, and any letter in uppercase entered on the
right side of this placeholder until the next < or I character, will
be converted to lowercase. If the letter is entered in lowercase,
nothing would happen. |
| | |
Conversion
Remover |
Removes the < or >
rule set on the left side of this placeholder. This means that, in this
placeholder and others on the right side, letters will not be converted
but will be kept "as is" |
| . |
Decimal
Symbol |
The decimal symbol must
be used. |
| , |
Thousands
Separator |
The character for the
thousands separator, which is the comma in US English, must be used. |
| : |
Time
Separator |
The character used to
separate the sections of a time value, which is ":" in US
English, must be used. |
| / |
Date
Separator |
The character used to
separate the sections of a date value, which is "/" in US
English, must be used. |
| $ |
Currency
Symbol |
The currency symbol,
which is $ is US and Canada, will be used |
| \ |
Escape
Sequence |
Makes the character
follow the escape sequence rules. |
| |
Any Other
Character |
Except for the
characters reviewed above, all other characters are kept "as
is". |
To programmatically specify a mask, create it in a string
and assign that string to the Mask property. Here is an example:
Public Sub InitializeComponent()
txtHomePhone = New MaskedTextBox
txtHomePhone.Location = New Point(20, 20)
txtHomePhone.Mask = "999-000-0000"
Controls.Add(txtHomePhone)
End Sub
This would produce:
|
The Placeholder Character |
|
When you create a mask, to indicate a placeholder for a
letter, a digit, or a symbol, the control uses a specific character. The default
character is the underscore. If you want, you can use a different character. To
support this, the MaskedTextBox class is equipped with the PromptChar
property. To change it visually, access the Properties window for the control,
click PromptChar and type the desired character. To programmatically specify the
character of the placeholders, assign a string to the PromptChar
property.
|
Entering the Wrong Character |
|
When using the control, the user must must know the rules to
follow based on the mask in the control: dates, telephone numbers, etc. The user
must also enter only the allowed characters. If the user enters an invalid
character, you can make the computer produce a sound (a beep). To assist you
with this, the MaskedTextBox is equipped with a Boolean property named BeepOnError.
When this property is set to True, if the user enters an invalid character, the
computer produces the beep sound:
Public Sub InitializeComponent()
txtHomePhone = New MaskedTextBox
txtHomePhone.Location = New Point(20, 20)
txtHomePhone.Mask = "999-000-0000"
txtHomePhone.BeepOnError = True
Controls.Add(txtHomePhone)
End Sub
Also, if the user enters an invalid character in the
control, the control fires a MaskInputRejected event. You can
(continuously) use this event to find out whenever the user enters a wrong
character so you can assist the user. Here is an example of implementing it:
Imports System.Drawing
Imports System.Windows.Forms
Module Exercise
Public Class Starter
Inherits Form
Friend WithEvents txtHomePhone As MaskedTextBox
Dim components As System.ComponentModel.Container
Public Sub New()
InitializeComponent()
End Sub
Public Sub InitializeComponent()
txtHomePhone = New MaskedTextBox
txtHomePhone.Location = New Point(20, 20)
txtHomePhone.Mask = "999-000-0000"
txtHomePhone.BeepOnError = True
Controls.Add(txtHomePhone)
End Sub
Private Sub MaskedInputWasRejected(ByVal sender As Object, _
ByVal e As MaskInputRejectedEventArgs) _
Handles txtHomePhone.MaskInputRejected
MsgBox("You entered an invalid character")
End Sub
End Class
Function Main() As Integer
Dim frmStart As Starter = New Starter
Application.Run(frmStart)
Return 0
End Function
End Module
|
Allowing the Placeholder Character for Input |
|
After creating the control, you can then use it in your
application. When the control comes up, it usually shows its placeholders using
a specific character. The most regularly used character is the underscore. Put
in reverse, the presence of the underscore indicates a placeholder. If you skip
a placeholder by pressing the Space bar, an underscore displays in the space you
left. This rule also apples for all other characters we reviewed. In some cases,
you may want to formally use the character in the placeholder. To illustrate
this, consider that you have applied a mask as &&&&&&.
When the control comes up, if Fe_GT4, this would be considered as Fe GT4 (with
an empty space where the _ was typed). In some cases, you may want the user to
be able to enter the character of the placeholder so that Fe_GT4 would produce Fe_GT4.
To assist you with this, the MaskedTextBox class is equipped with the AllowPromptAsInput
Boolean property.
|
Hiding the Placeholder When Focus is Lost |
|
By default, when the control comes up, it uses some
characters, such as _, to show its placeholder(s). This allows the user to know
where a character is expected and the number of characters that are expected.
After the user has used the control and pressed Tab or clicked another control,
the masked text box may still show its placeholders. If you want, you can hide
the placeholders when the control looses focus. To assist you with this, the MaskedTextBox
class is equipped with a Boolean property named HidePromptOnLeave. The
default value of this property is False, which indicates that the control
would always show its placeholder(s). Otherwise, you can set this property to
true to hide the placeholder character when the control loses focus. Here is an
example:
Public Sub InitializeComponent()
txtHomePhone = New MaskedTextBox
txtHomePhone.Location = New Point(20, 20)
txtHomePhone.Mask = "999-000-0000"
txtHomePhone.BeepOnError = True
txtHomePhone.HidePromptOnLeave = True
Controls.Add(txtHomePhone)
End Sub
|
Keeping the Format on Cut and Copy |
|
In some cases, the user can enter less than the number of
placeholders in the control. Unlike the regular text box, the user cannot enter
characters beyond the number of placeholders. As a class derived from the TextBoxBase
class, the masked text box is equipped with a context menu that allows the user
to cut, copy, and paste. When the user performs any of these operations, you may
want to control whether the mask characters would be included in the cut,
copied, or pasted text. To control this, the MaskedTextBox class is
equipped with a property named CutCopyMaskFormat, which is based on the MaskFormat
enumeration. Its members are: ExcludePromptAndLiterals, IncludeLiterals,
IncludePrompt, and IncludePromptAndLiterals.
|
Introduction to the Rich Text |
|
Text is considered rich if it can display various characters or paragraphs in
different styles and features that make it more attractive
than a regular ASCII text. Such a text can have some of its sections in different colors. Its paragraphs can have customized attributes or arranged independent of each other. Although you can create a complete rich but static text, the common use of a rich text is to let the
user process most of the formatting.
|
Creating a Rich Text Control |
|
To support a rich text, the .NET Framework provides the RichTextBox
control that is implement from the RichTextBox class.
Like TextBox, the RichTextBox class is based on TextBoxBase.
Therefore, to have right text in an application, from the Common Controls
section of the Toolbox, click RichTextBox and click the form.
To programmatically create rich text, declare a variable of type RichTextBox,
use the new operator to allocate memory for it, and add it to the Controls
collection of its parent. Here is an example:
Imports System.Drawing
Imports System.Windows.Forms
Module Exercise
Public Class Starter
Inherits Form
Private rchNote As RichTextBox
Dim components As System.ComponentModel.Container
Public Sub New()
InitializeComponent()
End Sub
Public Sub InitializeComponent()
rchNote = New RichTextBox()
Controls.Add(rchNote)
End Sub
End Class
Function Main() As Integer
Dim frmStart As Starter = New Starter
Application.Run(frmStart)
Return 0
End Function
End Module
|
Practical Learning: Starting a Rich Text Application
|
|
- Start Microsoft Visual Basic and create a new Windows Application named Notice1
- In the Solution Explorer, right-click Form1.vb and click Rename
- Type Editor.vb as the new name of the form and press Enter
- From the Dialogs section of the Toolbox, click OpenFileDialog
and click the form
- In the Properties window, click DefaultExt and type rtf
- Click (Name) and type dlgOpen
- Click Filter and type Rich Text Format (*.rtf)|*.rtf|Text File (*.txt)|*.txt|All Files|
- From the Dialogs section of the Toolbox, click SaveFileDialog
and click the form
- In the Properties window, click DefaultExt and type rtf
- Click (Name) and type dlgSave
- Click Filter and type Rich Text Format (*.rtf)|*.rtf|Text File
(*.txt)|*.txt|All Files|
- From the Common Controls section of the Toolbox, click RichTextBox
and click the form
- From the Menus & Toolbars section of the Toolbox, click MenuStrip and
click the form
- On the form, click Type Here, type File and press Enter
- Under File, click Type Here, type New and press Enter
- On the right side of File, click Type Here, type Edit and press
Enter
- Under Edit, click Type Here, type New and press Enter
- In the same way, complete the menu strip with the following items:
- On the form and click the rich text control
- In the Properties window, change the its properties as follows:
Name: rchEditor
AcceptsTab: True
Font: Times New Roman, 12pt
Dock: Fill
ScrollBars: Vertical
- Right-click the form and click View Code
- In the Class Name combo box, select (Editor Events)
- In the Method Name combo box, select Load and change the file as
follows:
Imports System.IO
Public Class Editor
Private CurrentFileName As String
Private Sub Form1_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles Me.Load
CurrentFileName = "<Not Allowed>"
rchEditor.Modified = False
End Sub
End Class
|
- In the Class Name combo box, select mnuEditUndo
- In the Method Name combo box, select Click and implement the event as follows:
Private Sub mnuEditUndo_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles mnuEditUndo.Click
rchEditor.Undo()
End Sub
|
- In the Class Name combo box, select mnuEditRedo
- In the Method Name combo box, select Click and implement the event as follows:
Private Sub mnuEditRedo_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles mnuEditUndo.Click
rchEditor.Redo()
End Sub
|
- In the Class Name combo box, select mnuEditCut
- In the Method Name combo box, select Click and implement the event as follows:
Private Sub mnuEditCut_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles mnuEditCut.Click
rchEditor.Cut()
End Sub
|
- In the Class Name combo box, select mnuEditCopy
- In the Method Name combo box, select Click and implement the event as follows:
Private Sub mnuEditCopy_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles mnuEditCopy.Click
rchEditor.Copy()
End Sub
|
- In the Class Name combo box, select mnuEditPaste
- In the Method Name combo box, select Click and implement the event as follows:
Private Sub mnuEditPaste_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles mnuEditPaste.Click
rchEditor.Paste()
End Sub
|
- In the Class Name combo box, select mnuEditSelectAll
- In the Method Name combo box, select Click and implement the event as follows:
Private Sub mnuSelectAll_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles mnuSelectAll.Click
rchEditor.SelectAll()
End Sub
|
- In the Class Name combo box, select mnuFormatWordWrap
- In the Method Name combo box, select Click and implement the event as follows:
Private Sub mnuFormatWordWrap_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles mnuFormatWordWrap.Click
rchEditor.WordWrap = True
End Sub
|
- Save all
|
The Text of a Rich Text Box |
|
Like the other graphical Windows controls, the right text
box uses the common characteristics such as the location, the size, the minimum
size, the maximum size, the anchor, the docking, the font, the ability to be
visible or hidden, the ability to be enabled or disabled, and the border style.
Like the TextBox control, the rich text control inherits various characteristics
from the TextBoxBase class, including the Text property, the Lines
collection, the read-only attribute, the ability to select and manipulate text. The rich text box also shares various
characteristics with the multi-line text box such as the Multiline
property, the scroll bars, the word wrap, the ability to accept the Tab and the
Enter keys. Here is an example:
Public Sub InitializeComponent()
rchNote = New RichTextBox()
rchNote.Size = New Size(Width, Height)
rchNote.Multiline = True
rchNote.ScrollBars = RichTextBoxScrollBars.Both
rchNote.AcceptsTab = True
rchNote.Font = New Font("Verdana", 10.0F)
Dim strLines As String() = _
{ _
"LeavingSydney", _
"When we decided to leave, we knew we were " & _
"making a hard decision. We had spent so much " & _
"time this had become our new home. A few " & _
"weeks or months before, we wanted to make " & _
"Sydney our newly found settlement, a " & _
"permanent place we could proudly call ours. " & _
"It appeared that, unpredictably, fate had " & _
"decided otherwise.", _
"Author: Arthur D. Pale", _
"Title: Stories Of My Life" _
}
rchNote.Lines = strLines
Controls.Add(rchNote)
Controls.Add(rchNote)
End Sub
|
Saving the Contents of a Rich Text Document |
|
After creating and formatting a rich text document, you may
want to save it for later use. To support this, the RichTextBox class
provides a method named named SaveFile that is overloaded with three
versions. One of the versions uses the following syntax:
Public Sub SaveFile(path As String)
This method takes as argument the name or path to a file. It
will save the file as RTF. If you want the user to save a file that is either
RTF, ASCII, or another format, to specify the desired format, you can use the
following version of the method:
Public Sub SaveFile(data As Stream, fileType As RichTextBoxStreamType)
As seen in the first version, the first argument is the name
or path of the file. The second argument allows you to specify the type of file
that is being saved, which could be a normal ASCII text. This argument is of
type RichTextBoxStreamType, which is an enumeration. The members of the RichTextBoxStreamType
enumeration are PlainText, RichNoOleObjs, RichText, TextTextOleObjs, or
TextTextOleObjs.
Instead of directly using the name of the file, you can
create it as a stream. In this case, the RichTextBox class provides the
following version of the SaveFile() method:
Public Sub SaveFile(path As String, fileType As RichTextBoxStreamType)
This version expects a Stream-based object such as a FileStream
variable.
To assist you with opening a rich text file, the RichTextBox
class is equipped with the LoadFile() method overloaded with three
versions. The simplest versions has the following syntax:
Public Sub LoadFile(path As String)
This method takes as argument the name or path to a file.
The file must be in RTF format. If it is not, the file will not be opened and
the compiler would throw an IOException exception. If you want to give
the user the ability to open different types of files, you should use the
following version of the LoadFile() method:
Public Sub LoadFile(data As Stream, fileType As RichTextBoxStreamType)
The first argument is the same as a the single argument of
the first version. The second argument allows you to specify the type of file
that is being opened, which could be a normal ASCII text. This argument is of
type RichTextBoxStreamType.
Instead of directly using the name of the file, you can
create it as a stream. In this case, the RichTextBox class provides the
following version of the LoadFile() method:
Public Sub LoadFile(path As String, fileType As RichTextBoxStreamType)
This version expects a Stream-based object such as a FileStream
variable.
|
Practical Learning:
Opening a Rich Text File
|
|
- In the Class Name combo box, click mnuFileNew
- In the Method Name combo box, select Click and implement the event as follows:
Private Sub mnuFileNew_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles mnuFileNew.Click
' This is the question the user will have to answer
Dim answer As MsgBoxResult = MsgBox( _
"The document has changed. Do you want to save it?" & _
vbCrLf & "Click\n" & _
"Yes:\tTo save the document and create a new one.\n" & _
"No:\tNot to save the document but create a new one.\n" & _
"Cancel:\tNot to do anything", _
MsgBoxStyle.YesNo Or MsgBoxStyle.Question, _
"Editor - Saving a File")
' When the user clicks File -> New to start a new document,
' before creating a new document,
' find out if the document is "dirty" ask the user whether to save or not
If rchEditor.Modified = True Then
' Present the message box to the user who
' will decide whether to save
If answer = MsgBoxResult.Yes Then
' If the user answers Yes
' Find out if the current document has never been saved
If CurrentFileName = "<Not Allowed>" Then
' If it has never been saved, then display the Save dialog box
If dlgSave.ShowDialog() = Windows.Forms.DialogResult.OK Then
' Save the file
rchEditor.SaveFile(dlgSave.FileName)
' Change the current file name to something not allowed
CurrentFileName = "<Not Allowed>"
' Display Untitled name of the current file on the title bar
Text = "Parasol - Untitled"
' Since the document has been saved and the user wants
' to create a new one, empty the control
rchEditor.Clear()
' Update the Modified attribute
rchEditor.Modified = False
Else ' the user had clicked Cancel, don't do anything
Exit Sub
End If
Else ' If the document was saved before, then simply update it
rchEditor.SaveFile(CurrentFileName)
' Change the current file name to something not allowed
CurrentFileName = "<Not Allowed>"
' Display Untitled name of the current file on the title bar
Text = "Parasol - Untitled"
rchEditor.Clear()
' Update the Modified attribute
rchEditor.Modified = False
End If
ElseIf answer = MsgBoxResult.No Then
' If the user answered No,
' then simply start a new document
rchEditor.Clear()
' Change the current file name to something not allowed
CurrentFileName = "<Not Allowed>"
' Display Untitled name of the current file on the title bar
Text = "Parasol - Untitled"
' Update the Modified attribute
rchEditor.Modified = False
Else ' If the user clicked Cancel, don't do anything
Exit Sub
End If
Else ' If the document was not modified, then start a new one
' If the user answered No,
' then simply start a new document
rchEditor.Clear()
' Change the current file name to something not allowed
CurrentFileName = "<Not Allowed>"
' Display Untitled name of the current file on the title bar
Text = "Parasol - Untitled"
' Update the Modified attribute
rchEditor.Modified = False
End If
End Sub
|
- In the Class Name combo box, click mnuFileOpen
- In the Method Name combo box, select Click and implement the event as follows:
Private Sub mnuFileOpen_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles mnuFileOpen.Click
' Find out if there was a document and if the document was "dirty"
If rchEditor.Modified = True Then
' Here is the question the user will answer
Dim answer As MsgBoxResult = MsgBox( _
"The document has changed. Do you want to save it?" & _
vbCrLf & "Click\n" & _
"Yes:\tTo save the document and open a new one.\n" & _
"No:\tNot to save the document but open a new one.\n" & _
"Cancel:\tNot to do anything", _
MsgBoxStyle.YesNoCancel Or MsgBoxStyle.Question, _
"Editor - Opening a File")
' Find out if the user wants to save the current document
If answer = MsgBoxResult.Yes Then
' Find out if this is a new document
If CurrentFileName = "<Not Allowed>" Then
' Since the user wants to save the document, display the Save dialog box
If dlgSave.ShowDialog() = Windows.Forms.DialogResult.OK Then
' Save the file
rchEditor.SaveFile(dlgSave.FileName)
Else
Exit Sub
End If
else
' This was not a new document,
' so, simply save it
rchEditor.SaveFile(CurrentFileName)
End If
ElseIf answer = MsgBoxResult.No Then
' If the user answered No to the question, don't save
' Simply open the file
If dlgOpen.ShowDialog() = Windows.Forms.DialogResult.OK Then
' Open the new document after letting the user select it
rchEditor.LoadFile(dlgOpen.FileName)
' Change the file name of our archives
CurrentFileName = dlgOpen.FileName
' Get the name of the file that the user selected
Dim fleParasol As FileInfo = New FileInfo(dlgOpen.FileName)
Text = "Parasol - " & fleParasol.Name
rchEditor.Modified = False
Else
Exit Sub
End If
else
Exit Sub
End If
else
If dlgOpen.ShowDialog() = Windows.Forms.DialogResult.OK Then
' Open the new document after letting the user select it
rchEditor.LoadFile(dlgOpen.FileName)
' Change the file name of our archives
CurrentFileName = dlgOpen.FileName
' Get the name of the file that the user selected
Dim fleParasol As FileInfo = New FileInfo(dlgOpen.FileName)
Text = "Parasol - " & fleParasol.Name
rchEditor.Modified = False
End If
End If
End Sub
|
- In the Class Name combo box, click mnuFileSave
- In the Method Name combo box, select Click and implement the event as follows:
Private Sub mnuFileSave_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles mnuFileSave.Click
' Find out if the current document has never been saved
' but is not empty
If (rchEditor.Modified = True) And _
(CurrentFileName = "<Not Allowed>") Then
' Since the document is dirty, display the Save As dialog box
If dlgSave.ShowDialog() = Windows.Forms.DialogResult.OK Then
' Retrieve the new name file and display
' the file in the rich edit control
rchEditor.SaveFile(dlgSave.FileName)
' Change/Update the global and complete name of the file,
' including its path
CurrentFileName = dlgSave.FileName
' Extract the name of the file
Dim fleParasol As FileInfo = New FileInfo(dlgSave.FileName)
' Display the name of the current file on the title bar
Text = "Parasol - " & fleParasol.Name
Else
Exit Sub
End If
Else
' It appears that this document already had a name
' but the document was previously modified
' Therefore, simply save it internally
rchEditor.SaveFile(CurrentFileName)
End If
End Sub
|
- In the Class Name combo box, click mnuFileSaveAs
- In the Method Name combo box, select Click and implement the event as follows:
Private Sub mnuFileSaveAs_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles mnuFileSaveAs.Click
If dlgSave.ShowDialog() = Windows.Forms.DialogResult.OK Then
rchEditor.SaveFile(dlgSave.FileName)
' Change the file name of our archives
CurrentFileName = dlgSave.FileName
' Get the name of the file that the user selected
Dim fleParasol As FileInfo = New FileInfo(dlgSave.FileName)
Text = "Parasol - " & fleParasol.Name
rchEditor.Modified = False
End If
End Sub
|
- In the Class Name combo box, click mnuFileExit
- In the Method Name combo box, select Click and implement the event as follows:
Private Sub mnuFileExit_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles mnuFileExit.Click
' Is the document dirty?
If rchEditor.Modified = True Then
' Since the document is dirty, find out if the user wants to save it
Dim Answer As MsgBoxResult = MsgBox( _
"The document has changed. Do you want to save it?" & _
vbCrLf & "Click\n" & _
"Yes:\tTo save the document and close the application.\n" & _
"No:\tNot to save the document but close the application.\n" & _
"Cancel:\tNot to do anything", _
MsgBoxStyle.YesNoCancel Or MsgBoxStyle.Question, _
"Parasol - Saving a File")
' If the user wants to save it
If Answer = MsgBoxResult.Yes Then
' Behave as if the user had clicked File . Save
mnuFileSave_Click(sender, e)
Close()
ElseIf Answer = MsgBoxResult.No Then
' If the user doesn't want to save the document
Close()
' The user cancelled the action: do nothing
Else
Exit Sub
End If
Else ' There is no action to take
Close()
End If
End Sub
|
- Return to the form
We saw that you could change the general font of a text box
and you can change the color of the characters. If you do this on a text box,
all of the characters are changed to the same font and the same color. One of
the extended properties of a rich text box over a regular text box is the
ability to change the font and/ the color of individual characters, words, or
paragraphs and the change applies only to the desired characters.
Before changing a character or a word, you must first select
it. To change the font of the text that is selected on the control, the selected
text is identified with the SelectionFont
property. To change the color of the text that is selected, the selected text is
identified with the SelectionColor
property.
To assist you with this, you can use the Font dialog box.
After selecting the character or word, you can transfer their attributes to the
Font dialog box before displaying it. After using the dialog box, if the user
clicks OK, you can retrieve the font and color characteristics then apply them
to the selected character or text.
|
Practical Learning: Formatting Text
|
|
- From the Dialogs section of the Toolbox, click FontDialog
and click the form
- Click (Name) and type dlgFont
- Double-click ShowColor to set its value to True
- Right-click the form and click View Code
- In the Class Name combo box, select mnuFormatFont
- In the Method Name combo box, select Click and implement the event as follows:
Private Sub mnuFormatFont_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles mnuFormatFont.Click
' Get the characteristics of the selected text
' Apply them to the Font dialog box
dlgFont.Font = rchEditor.SelectionFont
dlgFont.Color = rchEditor.SelectionColor
If dlgFont.ShowDialog() = Windows.Forms.DialogResult.OK Then
' Display the Font dialog box
' If the user clicks OK, get the characteristics of the font
' Apply them to the selected text of the Rich Edit control
rchEditor.SelectionFont = dlgFont.Font
rchEditor.SelectionColor = dlgFont.Color
End If
End Sub
|
- Save all
For a text-based control, a paragraph is a series of words that start with a letter or empty space until the flow of text is interrupted, which is usually
made with a carriage return, or the end of the document.
By itself, the paragraph controls its alignment and such details as Tab measurements or indentation. To set or change the properties of a paragraph, you must first select it. To select a paragraph, you don't need to formally select it or any portion of its text. As long as the cursor is positioned inside of the paragraph, any paragraph attribute you set or change would apply to the whole paragraph. To manipulate more than one paragraph at the same time, you or your user must select them. The paragraphs do not need to be wholly selected. As long as a section is selected on
it, a paragraph is considered selected.
The most common property of a paragraph is its alignment, which states whether the paragraph is positioned to the left, the center, or the right. This
characteristic is controlled by the
SelectionAlignment property. The SelectionAlignment property is
based on the HorizontalAlignment enumeration whose members are Left,
Center, and Right. Because this property is applied on
(individual) paragraphs, it is not available at design time.
To change the alignment at run time, assign the desired value to the
SelectionAlignment property.
|
Practical Learning: Aligning a Paragraph
|
|
- In the Class Name combo box, click mnuFormatAlignLeft
- In the Method Name combo box, select Click and implement the event as follows:
Private Sub mnuFormatAlignLeft_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles mnuFormatAlignLeft.Click
rchEditor.SelectionAlignment = HorizontalAlignment.Left
End Sub
|
- In the Class Name combo box, click mnuFormatAlignCenter
- In the Method Name combo box, select Click and implement the event as follows:
Private Sub mnuFormatAlignCenter_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles mnuFormatAlignCenter.Click
rchEditor.SelectionAlignment = HorizontalAlignment.Center
End Sub
|
- In the Class Name combo box, click mnuFormatAlignRight
- In the Method Name combo box, select Click and implement the event as follows:
Private Sub mnuFormatAlignRight_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles mnuFormatAlignRight.Click
rchEditor.SelectionAlignment = HorizontalAlignment.Right
End Sub
|
- Return to the form
|
The Indentation of a Paragraph |
|
Indentation is the number of empty characters that separate a paragraph
edge from one of the borders of the rich text control. Indentation refers to the
left side or the right side of a paragraph. Based on this, left indentation
refers to the number of empty characters from the left border of the rich text
control to the left edge of a paragraph. The rich text control provides
indentation through various properties.
To support indentation from the left side of a paragraph,
the RichTextBox class is equipped with a property named SelectionIndent property.
To indent from the right side, the RichTextBox is equipped with the SelectionRightIndent property.
|
Practical Learning: Indenting a Paragraph
|
|
- In the Class Name combo box, click mnuFormatLeftIndent
- In the Method Name combo box, select Click and implement the event as follows:
Private Sub mnuFormatLeftIndent_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles mnuFormatLeftIndent.Click
rchEditor.SelectionIndent += 10
End Sub
|
- In the Class Name combo box, click mnuFormatRightIndent
- In the Method Name combo box, select Click and implement the event as follows:
Private Sub mnuFormatRightIndent_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles mnuFormatRightIndent.Click
rchEditor.SelectionRightIndent += 10
End Sub
|
- Return to the form
Instead of just a regular section made only of text, you can create an unordered list of
lines or paragraphs in your document. To support this, the RichTextBox
class is equipped with a Boolean property named SelectionBullet. If you
set this property to false on a paragraph, the paragraph would start with a
bullet. If you apply this property to more than one consecutive paragraph, each
would start with a bullet.
|
Practical Learning: Using a Rich Text Control
|
|
- In the Class Name combo box, click mnuFormatBulletList
- In the Method Name combo box, select Click and implement their Click events as follows:
Private Sub mnuFormatBulletList_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles mnuFormatBulletList.Click
rchEditor.SelectionBullet = True
End Sub
|
- Execute the application and test the editor
- Close the form and return to your programming environment
|
|