
- •Using Your Sybex Electronic Book
- •Acknowledgments
- •Contents at a Glance
- •Introduction
- •Who Should Read This Book?
- •How About the Advanced Topics?
- •The Structure of the Book
- •How to Reach the Author
- •The Integrated Development Environment
- •The Start Page
- •Project Types
- •Your First VB Application
- •Making the Application More Robust
- •Making the Application More User-Friendly
- •The IDE Components
- •The IDE Menu
- •The Toolbox Window
- •The Solution Explorer
- •The Properties Window
- •The Output Window
- •The Command Window
- •The Task List Window
- •Environment Options
- •A Few Common Properties
- •A Few Common Events
- •A Few Common Methods
- •Building a Console Application
- •Summary
- •Building a Loan Calculator
- •How the Loan Application Works
- •Designing the User Interface
- •Programming the Loan Application
- •Validating the Data
- •Building a Math Calculator
- •Designing the User Interface
- •Programming the MathCalculator App
- •Adding More Features
- •Exception Handling
- •Taking the LoanCalculator to the Web
- •Working with Multiple Forms
- •Working with Multiple Projects
- •Executable Files
- •Distributing an Application
- •VB.NET at Work: Creating a Windows Installer
- •Finishing the Windows Installer
- •Running the Windows Installer
- •Verifying the Installation
- •Summary
- •Variables
- •Declaring Variables
- •Types of Variables
- •Converting Variable Types
- •User-Defined Data Types
- •Examining Variable Types
- •Why Declare Variables?
- •A Variable’s Scope
- •The Lifetime of a Variable
- •Constants
- •Arrays
- •Declaring Arrays
- •Initializing Arrays
- •Array Limits
- •Multidimensional Arrays
- •Dynamic Arrays
- •Arrays of Arrays
- •Variables as Objects
- •So, What’s an Object?
- •Formatting Numbers
- •Formatting Dates
- •Flow-Control Statements
- •Test Structures
- •Loop Structures
- •Nested Control Structures
- •The Exit Statement
- •Summary
- •Modular Coding
- •Subroutines
- •Functions
- •Arguments
- •Argument-Passing Mechanisms
- •Event-Handler Arguments
- •Passing an Unknown Number of Arguments
- •Named Arguments
- •More Types of Function Return Values
- •Overloading Functions
- •Summary
- •The Appearance of Forms
- •Properties of the Form Control
- •Placing Controls on Forms
- •Setting the TabOrder
- •VB.NET at Work: The Contacts Project
- •Anchoring and Docking
- •Loading and Showing Forms
- •The Startup Form
- •Controlling One Form from within Another
- •Forms vs. Dialog Boxes
- •VB.NET at Work: The MultipleForms Project
- •Designing Menus
- •The Menu Editor
- •Manipulating Menus at Runtime
- •Building Dynamic Forms at Runtime
- •The Form.Controls Collection
- •VB.NET at Work: The DynamicForm Project
- •Creating Event Handlers at Runtime
- •Summary
- •The TextBox Control
- •Basic Properties
- •Text-Manipulation Properties
- •Text-Selection Properties
- •Text-Selection Methods
- •Undoing Edits
- •VB.NET at Work: The TextPad Project
- •Capturing Keystrokes
- •The ListBox, CheckedListBox, and ComboBox Controls
- •Basic Properties
- •The Items Collection
- •VB.NET at Work: The ListDemo Project
- •Searching
- •The ComboBox Control
- •The ScrollBar and TrackBar Controls
- •The ScrollBar Control
- •The TrackBar Control
- •Summary
- •The Common Dialog Controls
- •Using the Common Dialog Controls
- •The Color Dialog Box
- •The Font Dialog Box
- •The Open and Save As Dialog Boxes
- •The Print Dialog Box
- •The RichTextBox Control
- •The RTF Language
- •Methods
- •Advanced Editing Features
- •Cutting and Pasting
- •Searching in a RichTextBox Control
- •Formatting URLs
- •VB.NET at Work: The RTFPad Project
- •Summary
- •What Is a Class?
- •Building the Minimal Class
- •Adding Code to the Minimal Class
- •Property Procedures
- •Customizing Default Members
- •Custom Enumerations
- •Using the SimpleClass in Other Projects
- •Firing Events
- •Shared Properties
- •Parsing a Filename String
- •Reusing the StringTools Class
- •Encapsulation and Abstraction
- •Inheritance
- •Inheriting Existing Classes
- •Polymorphism
- •The Shape Class
- •Object Constructors and Destructors
- •Instance and Shared Methods
- •Who Can Inherit What?
- •Parent Class Keywords
- •Derived Class Keyword
- •Parent Class Member Keywords
- •Derived Class Member Keyword
- •MyBase and MyClass
- •Summary
- •On Designing Windows Controls
- •Enhancing Existing Controls
- •Building the FocusedTextBox Control
- •Building Compound Controls
- •VB.NET at Work: The ColorEdit Control
- •VB.NET at Work: The Label3D Control
- •Raising Events
- •Using the Custom Control in Other Projects
- •VB.NET at Work: The Alarm Control
- •Designing Irregularly Shaped Controls
- •Designing Owner-Drawn Menus
- •Designing Owner-Drawn ListBox Controls
- •Using ActiveX Controls
- •Summary
- •Programming Word
- •Objects That Represent Text
- •The Documents Collection and the Document Object
- •Spell-Checking Documents
- •Programming Excel
- •The Worksheets Collection and the Worksheet Object
- •The Range Object
- •Using Excel as a Math Parser
- •Programming Outlook
- •Retrieving Information
- •Recursive Scanning of the Contacts Folder
- •Summary
- •Advanced Array Topics
- •Sorting Arrays
- •Searching Arrays
- •Other Array Operations
- •Array Limitations
- •The ArrayList Collection
- •Creating an ArrayList
- •Adding and Removing Items
- •The HashTable Collection
- •VB.NET at Work: The WordFrequencies Project
- •The SortedList Class
- •The IEnumerator and IComparer Interfaces
- •Enumerating Collections
- •Custom Sorting
- •Custom Sorting of a SortedList
- •The Serialization Class
- •Serializing Individual Objects
- •Serializing a Collection
- •Deserializing Objects
- •Summary
- •Handling Strings and Characters
- •The Char Class
- •The String Class
- •The StringBuilder Class
- •VB.NET at Work: The StringReversal Project
- •VB.NET at Work: The CountWords Project
- •Handling Dates
- •The DateTime Class
- •The TimeSpan Class
- •VB.NET at Work: Timing Operations
- •Summary
- •Accessing Folders and Files
- •The Directory Class
- •The File Class
- •The DirectoryInfo Class
- •The FileInfo Class
- •The Path Class
- •VB.NET at Work: The CustomExplorer Project
- •Accessing Files
- •The FileStream Object
- •The StreamWriter Object
- •The StreamReader Object
- •Sending Data to a File
- •The BinaryWriter Object
- •The BinaryReader Object
- •VB.NET at Work: The RecordSave Project
- •The FileSystemWatcher Component
- •Properties
- •Events
- •VB.NET at Work: The FileSystemWatcher Project
- •Summary
- •Displaying Images
- •The Image Object
- •Exchanging Images through the Clipboard
- •Drawing with GDI+
- •The Basic Drawing Objects
- •Drawing Shapes
- •Drawing Methods
- •Gradients
- •Coordinate Transformations
- •Specifying Transformations
- •VB.NET at Work: Plotting Functions
- •Bitmaps
- •Specifying Colors
- •Defining Colors
- •Processing Bitmaps
- •Summary
- •The Printing Objects
- •PrintDocument
- •PrintDialog
- •PageSetupDialog
- •PrintPreviewDialog
- •PrintPreviewControl
- •Printer and Page Properties
- •Page Geometry
- •Printing Examples
- •Printing Tabular Data
- •Printing Plain Text
- •Printing Bitmaps
- •Using the PrintPreviewControl
- •Summary
- •Examining the Advanced Controls
- •How Tree Structures Work
- •The ImageList Control
- •The TreeView Control
- •Adding New Items at Design Time
- •Adding New Items at Runtime
- •Assigning Images to Nodes
- •Scanning the TreeView Control
- •The ListView Control
- •The Columns Collection
- •The ListItem Object
- •The Items Collection
- •The SubItems Collection
- •Summary
- •Types of Errors
- •Design-Time Errors
- •Runtime Errors
- •Logic Errors
- •Exceptions and Structured Exception Handling
- •Studying an Exception
- •Getting a Handle on this Exception
- •Finally (!)
- •Customizing Exception Handling
- •Throwing Your Own Exceptions
- •Debugging
- •Breakpoints
- •Stepping Through
- •The Local and Watch Windows
- •Summary
- •Basic Concepts
- •Recursion in Real Life
- •A Simple Example
- •Recursion by Mistake
- •Scanning Folders Recursively
- •Describing a Recursive Procedure
- •Translating the Description to Code
- •The Stack Mechanism
- •Stack Defined
- •Recursive Programming and the Stack
- •Passing Arguments through the Stack
- •Special Issues in Recursive Programming
- •Knowing When to Use Recursive Programming
- •Summary
- •MDI Applications: The Basics
- •Building an MDI Application
- •Built-In Capabilities of MDI Applications
- •Accessing Child Forms
- •Ending an MDI Application
- •A Scrollable PictureBox
- •Summary
- •What Is a Database?
- •Relational Databases
- •Exploring the Northwind Database
- •Exploring the Pubs Database
- •Understanding Relations
- •The Server Explorer
- •Working with Tables
- •Relationships, Indices, and Constraints
- •Structured Query Language
- •Executing SQL Statements
- •Selection Queries
- •Calculated Fields
- •SQL Joins
- •Action Queries
- •The Query Builder
- •The Query Builder Interface
- •SQL at Work: Calculating Sums
- •SQL at Work: Counting Rows
- •Limiting the Selection
- •Parameterized Queries
- •Calculated Columns
- •Specifying Left, Right, and Inner Joins
- •Stored Procedures
- •Summary
- •How About XML?
- •Creating a DataSet
- •The DataGrid Control
- •Data Binding
- •VB.NET at Work: The ViewEditCustomers Project
- •Binding Complex Controls
- •Programming the DataAdapter Object
- •The Command Objects
- •The Command and DataReader Objects
- •VB.NET at Work: The DataReader Project
- •VB.NET at Work: The StoredProcedure Project
- •Summary
- •The Structure of a DataSet
- •Navigating the Tables of a DataSet
- •Updating DataSets
- •The DataForm Wizard
- •Handling Identity Fields
- •Transactions
- •Performing Update Operations
- •Updating Tables Manually
- •Building and Using Custom DataSets
- •Summary
- •An HTML Primer
- •HTML Code Elements
- •Server-Client Interaction
- •The Structure of HTML Documents
- •URLs and Hyperlinks
- •The Basic HTML Tags
- •Inserting Graphics
- •Tables
- •Forms and Controls
- •Processing Requests on the Server
- •Building a Web Application
- •Interacting with a Web Application
- •Maintaining State
- •The Web Controls
- •The ASP.NET Objects
- •The Page Object
- •The Response Object
- •The Request Object
- •The Server Object
- •Using Cookies
- •Handling Multiple Forms in Web Applications
- •Summary
- •The Data-Bound Web Controls
- •Simple Data Binding
- •Binding to DataSets
- •Is It a Grid, or a Table?
- •Getting Orders on the Web
- •The Forms of the ProductSearch Application
- •Paging Large DataSets
- •Customizing the Appearance of the DataGrid Control
- •Programming the Select Button
- •Summary
- •How to Serve the Web
- •Building a Web Service
- •Consuming the Web Service
- •Maintaining State in Web Services
- •A Data-Driven Web Service
- •Consuming the Products Web Service in VB
- •Summary

THE RICHTEXTBOX CONTROL 317
Formatting URLs
A new feature built into the RichTextBox control is the automatic formatting of URLs embedded in the text. To enable this feature, set the DetectURLs property to True. Then, as soon as the control determines that you’re entering a URL (usually after you enter the three Ws and the following period), it will format the text as a hyperlink. When the pointer rests over a hyperlink, its shape turns into a hand, just as it would in Internet Explorer. Run the RTFDemo project, enter a URL like www.sybex.com, and see how the RichTextBox control handles it.
In addition to formatting the URL, the RichTextBox control triggers the LinkClicked event when a hyperlink is clicked. To display the corresponding page from within your code, enter the following statement in the LinkClicked event handler:
Private Sub RichTextBox1_LinkClicked(ByVal sender As Object, _
ByVal e As System.Windows.Forms.LinkClickedEventArgs) _ Handles RichTextBox1.LinkClicked
System.Diagnostics.Process.Start(e.LinkText) End Sub
The System.Diagnostics.Process class provides the Start method, which starts an application. You can specify either the name of the executable or the path of a file. The Start method will look up the associated application and start it. As you can see, handling embedded URLs with the RichTextBox control is almost trivial.
Whatever application or file you specify in the Start method (Internet Explorer, for example) will run independently of your application, and the user may navigate to any other site, or close the browser and return to your application.
VB.NET at Work: The RTFPad Project
Creating a functional, even fancy, word processor based on the RichTextBox control is quite simple. The challenge is to provide a convenient interface that lets the user select text, apply attributes and styles to it, and then set the control’s properties accordingly. This chapter’s application does just that. It’s called RTFPad, and you can find it in this chapter’s folder on the CD.
The RTFPad application (see Figure 7.9) is based on the TextPad application developed in Chapter 6. It contains the same text-editing commands and some additional text-formatting commands that can only be implemented with the RichTextBox control; for example, it allows you to mix font styles in the text. This section examines the code and discusses a few topics unique to this application’s implementation with the RichTextBox control.
The two TrackBar controls above the RichTextBox control manipulate the indentation of the text. We’ve already explored this arrangement in the discussion of the TrackBar control in Chapter 6, but let’s review the operation of the two controls again. Each TrackBar control has a width of 816 pixels, which is equivalent to 8.5 inches on a monitor with a resolution of 96 dpi (dots per inch). The height of the TrackBar controls is 42 pixels and, unfortunately, they can’t be made smaller. The Minimum and Maximum properties of the control are of no significance, because all we really care about is the relative value of the control. Each time the user slides the top TrackBar control, the code sets the SelectionIndent property to the proper percentage of the control’s width. Because the SelectionHangingIndent includes the value of the SelectionIndent property, it also adjusts the setting of the SelectionHangingIndent property. Listing 7.4 is the code that’s executed when the upper TrackBar control is scrolled.
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |

318 Chapter 7 MORE WINDOWS CONTROLS
Listing 7.4: Setting the SelectionIndent Property
Private Sub TrackBar1_Scroll(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles TrackBar1.Scroll
Editor.SelectionIndent = Editor.Width * (TrackBar1.Value / TrackBar1.Maximum) Editor.SelectionHangingIndent = Editor.Width * _
(TrackBar2.Value / TrackBar2.Maximum) - Editor.SelectionIndent
End Sub
The second TrackBar control controls the hanging indentation of the selected text (the indentation of all text lines after the first one). Its Scroll event handler is presented in Listing 7.5.
Listing 7.5: Setting the SelectionHangingIndent Property
Private Sub TrackBar2_Scroll(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles TrackBar2.Scroll Editor.SelectionHangingIndent = Editor.Width * _
(TrackBar2.Value / TrackBar2.Maximum) - Editor.SelectionIndent
End Sub
Enter some text in the control, select one or more paragraphs, and check out the operation of the two sliders.
The Scroll events of the two TrackBar controls adjust the text’s indentation. The opposite action must take place when the user rests the pointer on another paragraph: the sliders’ positions must be adjusted to reflect the new indentation of the text. The selection of a new paragraph is signaled to the application by the SelChange event. The statements of Listing 7.6, which are executed from within the SelChange event, adjust the two slider controls to reflect the indentation of the text.
Listing 7.6: Setting the Slider Controls
Private Sub Editor_SelectionChanged(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Editor.SelectionChanged
If Editor.SelectionIndent = Nothing Then
TrackBar1.Value = TrackBar1.Minimum
TrackBar2.Value = TrackBar2.Minimum
Else
TrackBar1.Value = Editor.SelectionIndent * TrackBar1.Maximum / _
Editor.Width
TrackBar2.Value = (Editor.SelectionHangingIndent / Editor.Width) * _
TrackBar2.Maximum + TrackBar1.Value
End If
End Sub
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |

THE RICHTEXTBOX CONTROL 319
If the user selects multiple paragraphs with different indentations, the SelectionIndent property returns Nothing. The code examines the value of the SelectionIndent property and, if it’s Nothing, it moves both controls to the left edge. This way, the user can slide the controls and set the indentations for multiple paragraphs. Or you can set the sliders according to the indentation of the first or last paragraph in the selection. Some applications make the handles gray to indicate that the selected text doesn’t have uniform indentation, but unfortunately you can’t gray the sliders and keep them enabled. Of course, you can always design a custom control. The TrackBar controls are too tall for this type of interface and can’t be made very narrow (as a result, the interface of the RTFPad application isn’t very elegant).
The File Menu
The RTFPad application’s File menu contains the usual Open, Save, and Save As commands, which are implemented with the LoadFile and SaveFile methods. Listing 7.7 shows the implementation of the Open command in the File menu.
Listing 7.7: The Open Command
Private Sub FileOpen_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles FileOpen.Click If DiscardChanges() Then
OpenFileDialog1.Filter = “RTF Files|*.RTF|DOC Files|” & _ “*.DOC|Text Files|*.TXT|All Files|*.*”
If OpenFileDialog1.ShowDialog() = DialogResult.OK Then fName = OpenFileDialog1.FileName Editor.LoadFile(fName)
Editor.Modified = False End If
End If End Sub
The fName variable is declared on the Form level and holds the name of the currently open file. It’s set every time a new file is successfully opened and used by the Save command to automatically save the open file, without prompting the user for a filename.
DiscardChanges() is a function that returns a Boolean value, depending on whether the control’s contents can be discarded or not. The function starts by examining the Editor control’s Modified property. If True, it prompts the user as to whether he wants to discard the edits. Depending on the value of the Modified property and the user’s response, the function returns a Boolean value. If the DiscardChanges() function returns True, the program goes on and opens a new document. If the function returns False, the handler exits. Listing 7.8 shows the DiscardChanges() function.
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |

320 Chapter 7 MORE WINDOWS CONTROLS
Listing 7.8: The DiscardChanges() Function
Function DiscardChanges() As Boolean If Editor.Modified Then
Dim reply As MsgBoxResult
reply = MsgBox(“Text hasn’t been saved. Discard changes?”, _ MsgBoxStyle.YesNo)
If reply = MsgBoxResult.No Then Return False
Else
Return True End If
Else
Return True End If
End Function
The Modified property becomes True after typing the first character and isn’t reset back to False. The RichTextBox control doesn’t handle this property very intelligently and doesn’t reset it to False even after saving the control’s contents to a file. The application’s code sets the Editor.Modified property to False after creating a new document, as well as after saving the current document.
The Save As command (Listing 7.9) prompts the user for a filename and then stores the Editor control’s contents to the specified file. It also sets the fName variable to the file’s path, so that the Save command can use it. The fName variable is declared at the beginning of the code, outside any procedure.
Listing 7.9: The Save As Command
Private Sub FileSaveAs_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles FileSaveAs.Click SaveFileDialog1.Filter = “RTF Files|*.RTF|DOC Files|” & _
“*.DOC|Text Files|*.TXT|All Files|*.*” SaveFileDialog1.DefaultExt = “RTF”
If SaveFileDialog1.ShowDialog() = DialogResult.OK Then fName = SaveFileDialog1.FileName Editor.SaveFile(fName)
Editor.Modified = False End If
End Sub
The Save command’s code is similar, only it doesn’t prompt the user for a filename. It calls the SaveFile method passing the fName variable as argument. If the fName variable has no value (in other words, if a user attempts to save a new document with the Save command), then the code activates the event handler of the Save As command automatically. It also resets the control’s Modified property to False. The code behind the Save command is shown in Listing 7.10.
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |

THE RICHTEXTBOX CONTROL 321
Listing 7.10: The Save Command
Private Sub FileSave_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles FileSave.Click
If fName <> “” Then
Editor.SaveFile(fName)
Editor.Modified = False
Else
FileSaveAs_Click(sender, e)
End If
End Sub
The Edit Menu
The Edit menu contains the usual commands for exchanging data through the Clipboard (Copy, Cut, Paste), Undo/Redo commands, and a Find command to invoke the Find and Replace dialog box. All the commands are almost trivial, thanks to the functionality built into the control. The basic Cut, Copy, and Paste commands call the RichTextBox control’s Copy, Cut, and Paste methods to exchange information with other applications through the Clipboard. If you aren’t familiar with the Clipboard’s methods, all you need to know to follow this example are the SetText method, which copies a string to the Clipboard, and the GetText method, which copies the Clipboard’s contents to a string variable. The Copy, Cut, and Paste commands are shown in Listing 7.11.
Listing 7.11: The Copy, Cut, and Paste Commands
Private Sub EditCopy_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles EditCopy.Click
Editor.Copy()
End Sub
Private Sub EditCut_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles EditCut.Click
Editor.Cut()
End Sub
Private Sub EditPaste_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles EditPaste.Click
Try
Editor.Paste()
Catch exc As Exception
MsgBox(“Can’t paste current clipboard’s contents”)
End Try
End Sub
As you recall from the discussion of the Paste command, we can’t use the CanPaste method, because it’s not trivial; you have to handle each data type differently. By using the exception handler, we allow the user to paste all types of data the RichTextBox control can accept, and we display a message when an error occurs.
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |

322 Chapter 7 MORE WINDOWS CONTROLS
The Undo and Redo commands of the Edit menu are coded as follows. First, we must display the name of the action to be undone or redone in the Edit menu. When the Edit menu is selected, the Select event is fired. This event takes place before the Click event, so I’ve inserted a few lines of code that read the name of the most recent action that can be undone or redone and print it next to the Undo or Redo command. If there’s no such action, the program will disable the corresponding command. Listing 7.12 is the code that’s executed when the Edit menu is dropped.
Listing 7.12: Setting the Captions of the Undo and Redo Commands
Private Sub EditMenu_Select(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles EditMenu.Select
If Editor.UndoActionName <> “” Then
EditUndo.Text = “Undo “ & Editor.UndoActionName
EditUndo.Enabled = True
Else
EditUndo.Text = “Undo”
EditUndo.Enabled = False
End If
If Editor.RedoActionName <> “” Then
EditRedo.Text = “Redo “ & Editor.RedoActionName
EditRedo.Enabled = True
Else
EditRedo.Text = “Redo”
EditRedo.Enabled = False
End If
End Sub
When the user selects one of the Undo and Redo commands, we simply call the appropriate method from within the menu item’s Click event handler (Listing 7.13).
Listing 7.13: Undoing and Redoing Actions
Private Sub EditUndo_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles EditUndo.Click
If Editor.CanUndo Then Editor.Undo()
End Sub
Private Sub EditRedo_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles EditRedo.Click
If Editor.CanRedo Then Editor.Redo()
End Sub
Calling the CanUndo and CanRedo method is unnecessary, because if there’s no corresponding action the two menu items will be disabled, but an additional check is no harm. Should there be an “unknown” action that the control can’t undo, these If statements will prevent the control from attempting to perform the undo action.
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |

THE RICHTEXTBOX CONTROL 323
The Format Menu
The commands of the Format menu control the alignment of the text and the font attributes of the current selection. The Font command displays the Font dialog box and then assigns the font selected by the user to the current selection. Listing 7.14 shows the code behind the Font command.
Listing 7.14: The Font Command
Private Sub FormatFont_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles FormatFont.Click
If Not Editor.SelectionFont Is Nothing Then
FontDialog1.Font = Editor.SelectionFont
Else
FontDialog1.Font = Nothing
End If
If FontDialog1.ShowDialog() = DialogResult.OK Then
Editor.SelectionFont = FontDialog1.Font
End If
End Sub
Notice that the code preselects a font on the dialog box, which is the font of the current selection. If the current selection isn’t formatted with a single font, then no font is preselected. You can modify the code so that it displays the font of the first character in the selection.
To enable the Apply button of the Font dialog box, set the control’s ShowApply property to True and insert the following statement in its Apply event handler. Select the FontDialog1 control in the Objects drop-down list of the code editor, and then select the Apply event in the Events dropdown list. When the declaration of the event handler appears, insert the statement that applies the font selected on the Font dialog box to the current selection:
Private Sub FontDialog1_Apply(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles FontDialog1.Apply Editor.SelectionFont = FontDialog1.Font
End Sub
The options of the Align menu set the RichTextBox control’s SelectionAlignment property to different members of the HorizontalAlignment enumeration. The Align Left command, for example, is implemented with the following statement:
Editor.SelectionAlignment = HorizontalAlignment.Left
The Search & Replace Dialog Box
The Find command in the Edit menu opens the dialog box shown in Figure 7.14, which the user can use to perform various search and replace operations (whole-word or case-sensitive match, or both). The code behind the Command buttons on this form is quite similar to the code for the Search & Replace dialog box of the TextPad application, with one basic difference: it uses the control’s Find method. The Find method of the RichTextBox control performs all types of searches, and some of its options are not available with the InStr() function.
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |

324 Chapter 7 MORE WINDOWS CONTROLS
Figure 7.14
The Search & Replace dialog box of the RTFPad application
To invoke the Search & Replace dialog box (Listing 7.15), the Find command calls the Show method of a variable that represents the dialog box.
Listing 7.15: Displaying the Search & Replace Dialog Box
Private Sub EditFind_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles EditFind.Click If fndForm Is Nothing Then
fndForm = New FindForm() End If
fndForm.Show() End Sub
fndForm is declared on the Form level with the following statement:
Dim fndForm As FindForm
The dialog box should have access to the Editor control on the main form. To allow the dialog box to manipulate the RichTextBox control on the main form, the program declared a public shared variable with the following statement:
Public Shared RTFBox As RichTextBox
This variable is initialized to the Editor RichTextBox control in the form’s Load event handler, shown in Listing 7.16.
Listing 7.16: The Main Form’s Load Event Handler
Private Sub EditorForm_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
RTFBox = Editor
End Sub
The Find method of the RichTextBox control allows you to perform case-sensitive or -insensitive searches, as well as search for whole words only. These options are specified through an argument of the RichTextBoxFinds type. The SetSearchMode() function (Listing 7.17) examines the settings of the two check boxes at the bottom of the form and sets this option.
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |

THE RICHTEXTBOX CONTROL 325
Listing 7.17: Setting the Search Options
Function SetSearchMode() As RichTextBoxFinds Dim mode As RichTextBoxFinds
If chkCase.Checked = True Then
mode = RichTextBoxFinds.MatchCase Else
mode = RichTextBoxFinds.None End If
If chkWord.Checked = True Then
mode = mode Or RichTextBoxFinds.WholeWord Else
mode = mode Or RichTextBoxFinds.None End If
SetSearchMode = mode End Function
The Find and Find Next methods call this function to retrieve the constant that determines the type of the search specified by the user on the form. This value is then passed to the Find method. Listing 7.18 shows the code behind the Find and Find Next buttons.
Listing 7.18: The Find and Find Next Commands
Private Sub bttnFind_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles bttnFind.Click Dim wordAt As Integer
Dim srchMode As RichTextBoxFinds srchMode = SetSearchMode()
wordAt = EditorForm.RTFBox.Find(txtSearchWord.Text, 0, srchMode) If wordAt = -1 Then
MsgBox(“Can’t find word”) Exit Sub
End If
EditorForm.RTFBox.Select(wordAt, txtSearchWord.Text.Length) bttnFindNext.Enabled = True
bttnReplace.Enabled = True bttnReplaceAll.Enabled = True EditorForm.RTFBox.ScrollToCaret()
End Sub
Private Sub bttnFindNext_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles bttnFindNext.Click Dim selStart As Integer
Dim srchMode As CompareMethod srchMode = SetSearchMode()
selStart = InStr(EditorForm.RTFBox.SelectionStart + 2, _ EditorForm.RTFBox.Text, txtSearchWord.Text, srchMode)
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |