RichTextBox

Table of contents:

The RichTextBox is similar to the TextBox, but it has additional formatting capabilities. Whereas the TextBox control allows the Font property to be set for the entire control, the RichTextBox allows you to set the Font, as well as other formatting properties, for selections within the text displayed in the control.

When considering the difference between the TextBox and RichTextBox controls, compare Notepad and WordPad, the two text editors that are included with Windows. Notepad, based on the TextBox control, has no formatting applicable to selections within the text. WordPad, on the other hand, is practically a full-fledged word processor, with such features as bullets, hanging indents, fonts, and character styles applicable to selections within the text.

The default file format for the RichTextBox is the Rich Text Format (RTF), a file format that can carry formatting information.

The RichTextBox control inherits all the properties, methods, and events from the TextBoxBase class, so it behaves much like the TextBox control. In addition, it has many properties, methods, and events specific to itself. Many of the most commonly used RichTextBox-specific properties are listed in Table 12-7.

Rich Text Format (RTF)

This format was developed by Microsoft in the mid-1980s to permit easy interchange of formatted text between various applications. RTF Version 1.7, released in August 2001, adds support for features found in Word 2002. The specification can be downloaded as a Word document by going to http://msdn.microsoft.com/downloads/default.asp, and then drilling down to Office Solutions Development Microsoft Word Rich Text Format Specification, Version 1.7.

Since Microsoft Word can read and write RTF files interchangeably with Word document files, virtually all formatting constructs available to a Word document can be represented in an RTF file. RTF is the native format of WordPad, the lightweight word processor included as part of Windows. If an application needs to read or write a file with formatting, RTF is a relatively convenient (relative to the native Word document format, that is) way to accomplish that task, with a set of features more congruent than HTML with modern word processors.

That said, RTF is difficult to work with, primarily because it is designed to be read by RTF readers (word processors, etc.) and not people. RTF control words are case sensitive. Also, whitespace is strictly controlled, so inadvertent spaces in the wrong place in the file will appear as extra spaces in the displayed text. Just to make life interesting for developers writing an RTF writer, there is no way to comment out part of the file. There is no object model, and constructing or deconstructing RTF files always involves a lot of text parsing and manipulation.

RTF files consist primarily of low-order ASCII characters, although it does support switching code pages to use full Unicode character sets, and you can access the high-order ASCII characters by using escape sequences. The file contains the backslash character used as a control character, control words (a keyword preceded by a backslash), and the text to be displayed. The file also contains control groups enclosed within curly braces ({ }).

An RTF file itself is considered a group, so it must be enclosed in curly braces. The file consists of a header and a document. The header tells the reader that this is an RTF file. It may also include control groups describing document wide features, such as tables of fonts, files, colors, stylesheets, or revision markings. The document contains the plain text to be displayed, specific formatting commands, and an information group describing the text. The document is not contained within its own set of curly braces.

A minimal RTF file might look something like this:

{
tfpard Some RTF text.}

The entire file is contained within braces. The header consists of one control word: the tf tag tells the reader that this is an RTF file. Often, the tf is followed by an integer indicating the major specification revision number, as shown in Example 12-5, which uses Rev. 1. The pard control word, representing a default paragraph, is the beginning of the document. Some RTF text. is the actual displayed content of the file.

To work with RTF files, use either Word or WordPad to generate sample files and to test your results. Be aware, however, that both programs insert copious quantities of default control words, most of which are unnecessary for an RTF reader to render the document correctly.

Table 12-7. Selected RichTextBox properties

Property

Value type

Description

AllowDrop

Boolean

Read/write. If true, drag-and-drop operations allowed for the control.

AutoWordSelection

Boolean

Read/write. If false (the default), automatic word selection is disabled. If true, selecting any part of a word in the control causes the entire word to be selected. Note: this can be seen when extending a selection from one word to the next with the mouse, but not if extending the selection with the keyboard.

BulletIndent

Integer

Read/write. Number of pixels to indent text after a bullet character when the bullet style is applied. Default is zero.

CanRedo

Boolean

Read-only. If true, the operations that have been undone can be reapplied. Used in conjunction with the Redo method, described in Table 12-11.

DetectUrls

Boolean

Read/write. If true (the default), the control will automatically detect and format URLs as a link when they are entered in the control. The LinkClicked event allows handling of clicks on the link.

RightMargin

Integer

Read/write. Maximum width, in pixels, of each line of text, measured from the left edge of the control (that is correct, the left edge). Text hitting that margin will be treated as though it had hit the right edge of the control.

Rtf

String

Read/write. The text to be displayed by the control in Rich Text Format (RTF). See the sidebar for a description of RTF.

ScrollBars

RichTextBoxScrollBars

Read/write. Specifies which scrollbars are displayed in the control and under what circumstances. Valid values are members of the RichTextBoxScrollBars enumeration, listed in Table 12-10.

SelectedRtf

String

Read/write. The selected text, including the RTF formatting codes.

SelectionAlignment

HorizontalAlignment

Read/write. Valid values are members of the Horizontal-Alignment enumeration listed in Table 12-8.

SelectionBullet

Boolean

Read/write. If true, the current selection or insertion point will have the bullet style applied.

SelectionCharOffset

Integer

Read/write. Number of pixels that selected text appears above or below the baseline. Valid values can range from -2000-2000. Positive values raise the text above the baseline; negative values lower the text. Default is zero, which puts the text on the baseline.

SelectionColor

Color

Read/write. The color of the currently selected text or the text on the current line.

SelectionFont

Font

Read/write. The Font of the currently selected text or the text on the current line. If selection contains more than one font, the value is null (in C#) or Nothing (in VB.NET).

SelectionHangingIndent

Integer

Read/write. Distance, in pixels, from the left edge of the first line in the paragraph to the left edge of second and subsequent lines in that paragraph.

SelectionIndent

Integer

Read/write. Distance, in pixels, from the left edge of the paragraph to the left edge of the control.

SelectionProtected

Boolean

Read/write. If false (the default), the currently selected text or the paragraph containing the insertion point is not protected. If true, the Protected event is raised if the user attempts to change the current text selection. Will return true only if the entire selection consists of protected text.

SelectionRightIndent

Integer

Read/write. Distance, in pixels, from the right edge of the paragraph to the right edge of the control.

SelectionTabs

Integer array

Read/write. An array of integers in which each member specifies a tab offset, in pixels.

SelectionType

RichTextBoxSelectionTypes

Read-only. Bitwise combination of values from the RichTextBoxSelectionTypes enumeration, listed in Table 12-9.

ShowSelectionMargin

Boolean

Read/write. If true, the control contains a selection margin along the left side of the control. Clicking in the selection margin selects the adjacent line of text; double-clicking selects the entire paragraph. Default is false.

ZoomFactor

Float / single (VB.NET)

Read-only. Measures how fast the application is. Just kidding. Actually, it is read/write, getting or setting the current zoom level when viewing the control. Legal values range from 0.74 to 64.0. 1.0 indicates that no zoom is applied. Works best with TrueType fonts. Non-TrueType fonts use integer values for ZoomFactor.

Table 12-8. HorizontalAlignment enumeration values

Value

Description

Center

Aligned in the center of the control.

Left

Aligned to the left of the control.

Right

Aligned to the right of the control.

Table 12-9. RichTextBoxSelectionTypes enumeration values

Value

Description

Empty

No text in the current selection.

MultiChar

More than one text character is currently selected.

MultiObject

More than one OLE object is currently selected.

Object

At least one OLE object is currently selected.

Text

Only text is currently selected.

Table 12-10. RichTextBoxScrollBars enumeration values

Value

Description

Both

Displays both horizontal and vertical scrollbars when the text is either wider or longer than the text box.

ForcedBoth

Always displays both horizontal and vertical scrollbars.

ForcedHorizontal

Always displays a horizontal scrollbar, as long as the RichTextBox WordWrap property is set to false.

ForcedVertical

Always displays a vertical scrollbar.

Horizontal

Displays a horizontal scrollbar if the text is wider than the text box, as long as the RichTextBox WordWrap property is set to false.

None

No scrollbars are displayed.

Vertical

Displays a vertical scrollbar if the text is longer than the text box.

The properties listed in Table 12-7 that begin with the word "Selection," such as SelectionAlignment or SelectionBullet, behave similarly: the property applies to the currently selected text. However, if there is currently no selected text, then it will generally apply to the current text insertion point (the caret) and to all text on that line (from the prior new line character to the next new line character). If text is entered after the insertion point, the property will apply to it, until the property is changed. Some selection properties, such as SelectionFont, do not apply to pre-existing but non-selected text, but only to currently selected text, or text entered at the insertion point.

The listing in Example 12-5 demonstrates many RichTextBox properties using C#. Since this program is lengthy and virtually identical in VB.NET (aside from the normal syntactic differences), only the C# version will be presented in its entirety. Sections of code that are significantly different in VB.NET will be shown. The complete VB.NET source code can be downloaded from http://www.LibertyAssociates.com (click on Books).

This example creates a stripped-down version of WordPad, with a rich text box that fills the form client area and a truncated menu. (Menus will be covered in detail in Chapter 18.) Many properties and menu items used in this example are the same as those demonstrated for TextBox controls in Example 12-1 and Example 12-2. An analysis of the code follows.

When the program is compiled and run, you will get something like Figure 12-3.

Figure 12-3. RichTextBox

figs/pnwa_1203.gif

Example 12-5. RichTextBox properties in C# (RichTextBoxes.cs)

figs/csharpicon.gif

using System;
using System.Drawing;
using System.Windows.Forms;
using System.IO;
 
namespace ProgrammingWinApps
{
 public class RichTextBoxes : Form
 {
 RichTextBox rtxt;
 
 public RichTextBoxes( )
 {
 Text = "RichTextBox";
 Size = new Size(400, 500);
 
 rtxt = new RichTextBox( );
 rtxt.Parent = this;
 rtxt.Text = "Enter text here.";
 rtxt.Rtf = "{\rtf1\pard Some RTF text.}";
 rtxt.Multiline = true;
 rtxt.BorderStyle = BorderStyle.Fixed3D;
 rtxt.WordWrap = false;
 rtxt.ScrollBars = RichTextBoxScrollBars.ForcedBoth;
 rtxt.Dock = DockStyle.Fill;
 rtxt.DetectUrls = true; // true is the default value
 rtxt.AutoWordSelection = true;
 rtxt.BulletIndent = 10;
 rtxt.ShowSelectionMargin = true;
 
 // Menus
 // File menu items
 MenuItem mnuImport = new MenuItem("&Import",
 new EventHandler(mnuImport_Click));
 MenuItem mnuFile = new MenuItem("&File",
 new MenuItem[ ] {mnuImport});
 
 // Edit menu items
 MenuItem mnuDash1 = new MenuItem("-");
 MenuItem mnuDash2 = new MenuItem("-");
 MenuItem mnuUndo = new MenuItem("&Undo",
 new EventHandler(mnuUndo_Click),
 Shortcut.CtrlZ);
 MenuItem mnuCut = new MenuItem("Cu&t",
 new EventHandler(mnuCut_Click),
 Shortcut.CtrlX);
 MenuItem mnuCopy = new MenuItem("&Copy",
 new EventHandler(mnuCopy_Click),
 Shortcut.CtrlC);
 MenuItem mnuCopyRtf = new MenuItem("Copy &Rtf",
 new EventHandler(mnuCopyRtf_Click));
 MenuItem mnuPaste = new MenuItem("&Paste",
 new EventHandler(mnuPaste_Click),
 Shortcut.CtrlV);
 MenuItem mnuDelete = new MenuItem("&Delete",
 new EventHandler(mnuDelete_Click));
 MenuItem mnuSelectAll = new MenuItem("Select &All",
 new EventHandler(mnuSelectAll_Click),
 Shortcut.CtrlA);
 MenuItem mnuSelect5 = new MenuItem("Select First &5",
 new EventHandler(mnuSelect5_Click),
 Shortcut.Ctrl5);
 MenuItem mnuClear = new MenuItem("Clea&r",
 new EventHandler(mnuClear_Click));
 MenuItem mnuEdit = new MenuItem("&Edit",
 new MenuItem[ ] {mnuUndo, mnuDash1, 
 mnuCut, mnuCopy, mnuCopyRtf, mnuPaste, 
 mnuDelete, mnuDash2, mnuSelectAll, 
 mnuSelect5, mnuClear});
 
 // View Menu items
 MenuItem mnuScrollToCaret = new MenuItem("&Scroll to Caret",
 new EventHandler(mnuScrollToCaret_Click));
 MenuItem mnuView = new MenuItem("&View",
 new MenuItem[ ] {mnuScrollToCaret});
 
 // Alignment menu items
 MenuItem mnuAlignLeft = new MenuItem("Align&Left",
 new EventHandler(mnuAlignLeft_Click));
 MenuItem mnuAlignRight = new MenuItem("Align&Right",
 new EventHandler(mnuAlignRight_Click));
 MenuItem mnuAlignCenter = new MenuItem("Align&Center",
 new EventHandler(mnuAlignCenter_Click));
 
 // Format Menu items
 MenuItem mnuBullet = new MenuItem("&Bullet",
 new EventHandler(mnuBullet_Click));
 MenuItem mnuAlign = new MenuItem("&Align",
 new MenuItem[ ] {mnuAlignLeft, 
 mnuAlignRight, mnuAlignCenter});
 MenuItem mnuRed = new MenuItem("&Red",
 new EventHandler(mnuRed_Click));
 MenuItem mnuBold = new MenuItem("Bo&ld",
 new EventHandler(mnuBold_Click));
 MenuItem mnuHang = new MenuItem("&Hanging Indent",
 new EventHandler(mnuHang_Click));
 MenuItem mnuIndent = new MenuItem("&Indent",
 new EventHandler(mnuIndent_Click));
 MenuItem mnuRightIndent = new MenuItem("&Right Indent",
 new EventHandler(mnuRightIndent_Click));
 MenuItem mnuFormat = new MenuItem("For&mat",
 new MenuItem[ ] {mnuBullet, mnuAlign, 
 mnuRed, mnuBold, mnuHang, mnuIndent, 
 mnuRightIndent});
 
 // Main menu
 Menu = new MainMenu(new MenuItem[ ] {mnuFile, mnuEdit, 
 mnuView, mnuFormat});
 } // close for constructor
 
 static void Main( ) 
 {
 Application.Run(new RichTextBoxes( ));
 }
 
 private void mnuImport_Click(object sender, EventArgs e)
 {
 OpenFileDialog ofd = new OpenFileDialog( );
 ofd.InitialDirectory = @"c:";
 ofd.Filter = "RTF files (*.rtf)|*.rtf|" +
 "All files (*.*)|*.*";
 ofd.FilterIndex = 1; // 1 based index
 
 if (ofd.ShowDialog( ) = = DialogResult.OK)
 {
 try
 {
 StreamReader reader = new StreamReader(ofd.FileName);
 rtxt.Rtf = reader.ReadToEnd( );
 reader.Close( );
 }
 catch (Exception ex)
 {
 MessageBox.Show(ex.Message);
 return;
 }
 }
 }
 
 private void mnuUndo_Click(object sender, EventArgs e)
 {
 if (rtxt.CanUndo = = true)
 {
 rtxt.Undo( );
 rtxt.ClearUndo( );
 }
 }
 
 private void mnuCut_Click(object sender, EventArgs e)
 {
 if (rtxt.SelectedText != "")
 rtxt.Cut( );
 }
 
 private void mnuCopy_Click(object sender, EventArgs e)
 {
 if (rtxt.SelectionLength > 0)
 rtxt.Copy( );
 }
 
 private void mnuCopyRtf_Click(object sender, EventArgs e)
 {
 if (rtxt.SelectionLength > 0)
 {
 Clipboard.SetDataObject(rtxt.SelectedRtf);
 }
 }
 
 private void mnuPaste_Click(object sender, EventArgs e)
 {
 if (Clipboard.GetDataObject( ).GetDataPresent(DataFormats.Text) 
 = = true)
 {
 if (rtxt.CanUndo = = true)
 {
 if (rtxt.SelectionLength > 0)
 {
 if (MessageBox.Show(
 "Do you want to overwrite the currently selected " + 
 "text?", 
 "Cut & Paste", MessageBoxButtons.YesNo) = =
 DialogResult.No)
 rtxt.SelectionStart = rtxt.SelectionStart + 
 rtxt.SelectionLength;
 }
 rtxt.Paste( );
 }
 }
 }
 
 private void mnuDelete_Click(object sender, EventArgs e)
 {
 if (rtxt.SelectionLength > 0)
 rtxt.SelectedText = "";
 }
 
 private void mnuClear_Click(object sender, EventArgs e)
 {
 rtxt.Clear( );
 }
 
 
 private void mnuSelect5_Click(object sender, EventArgs e)
 {
 if (rtxt.Text.Length >= 5)
 {
 rtxt.Select(0,5);
 }
 else
 {
 rtxt.Select(0,rtxt.Text.Length);
 }
 }
 
 private void mnuSelectAll_Click(object sender, EventArgs e)
 {
 rtxt.SelectAll( );
 }
 
 private void mnuScrollToCaret_Click(object sender, EventArgs e)
 {
 rtxt.ScrollToCaret( );
 }
 
 private void mnuBullet_Click(object sender, EventArgs e)
 {
 rtxt.SelectionBullet = !rtxt.SelectionBullet;
 }
 
 private void mnuAlignLeft_Click(object sender, EventArgs e)
 {
 rtxt.SelectionAlignment = HorizontalAlignment.Left;
 }
 
 private void mnuAlignRight_Click(object sender, EventArgs e)
 {
 rtxt.SelectionAlignment = HorizontalAlignment.Right;
 }
 
 private void mnuAlignCenter_Click(object sender, EventArgs e)
 {
 rtxt.SelectionAlignment = HorizontalAlignment.Center;
 }
 
 private void mnuRed_Click(object sender, EventArgs e)
 {
 if (rtxt.SelectionColor = = Color.Red)
 rtxt.SelectionColor = Color.Black;
 else
 rtxt.SelectionColor = Color.Red;
 }
 
 private void mnuBold_Click(object sender, EventArgs e)
 {
 if (rtxt.SelectionFont.Bold )
 rtxt.SelectionFont = 
 new Font(rtxt.SelectionFont, FontStyle.Regular);
 else
 rtxt.SelectionFont = 
 new Font(rtxt.SelectionFont, FontStyle.Bold);
 }
 
 private void mnuHang_Click(object sender, EventArgs e)
 {
 if (rtxt.SelectionHangingIndent = = 10 )
 rtxt.SelectionHangingIndent = 0;
 else
 rtxt.SelectionHangingIndent = 10;
 }
 
 private void mnuIndent_Click(object sender, EventArgs e)
 {
 if (rtxt.SelectionIndent = = 10 )
 rtxt.SelectionIndent = 0;
 else
 rtxt.SelectionIndent = 10;
 }
 
 private void mnuRightIndent_Click(object sender, EventArgs e)
 {
 if (rtxt.SelectionRightIndent = = 50 )
 rtxt.SelectionRightIndent = 0;
 else
 rtxt.SelectionRightIndent = 50;
 }
 
 } // close for form class
} // close form namespace

The program starts off by declaring a single class member variable, rtxt, representing the RichTextBox control. The equivalent VB.NET line of code would be:

figs/vbicon.gif

dim rtxt as RichTextBox

In the constructor, both a Text property and an Rtf property are set. However, when you run the program, you will see that only the Rtf property is displayed in the control. If the order of these two lines of code are reversed, then the Text property rather than the Rtf would be visible in the control. Both properties control what is displayed in the control: the Text property assumes plain text and the Rtf property assumes valid RTF formatted text.

Since RTF files use a backslash as a control character, and the backslash character is an escape character in C#, you must double the backslashes before they are properly escaped. Alternatively, you can use an @-quoted string literal in C#, as in:

figs/csharpicon.gif

rtxt.Rtf = @"{
tf1pard Some RTF text.}";

VB.NET does not use the backslash character as an escape character, so the equivalent line of code in VB.NET would be:

figs/vbicon.gif

rtxt.Rtf = "{
tf1pard Some RTF text.}"

The ScrollBars property is set to ForcedBoth, which causes both a horizontal and vertical scrollbar to be present at all times, even if the contents of the control do not warrant them.

A horizontal scrollbar will not display unless the WordWrap property is set to false. If, in addition, the ShowSelectionMargin property is set to true (as is the case in Example 12-5), then a horizontal scrollbar will always display when the ScrollBars property is set to Horizontal, even if the text length does not warrant it (as with ForcedHorizontal behavior).

The DockStyle property is set to Fill, which forces the rich text box to fill the client area of the form. The DockStyle property was explained in Chapter 7.

The DetectUrls property is set to true, although the line is not strictly necessary, since this is the default value. However, by changing it to false, you can see the different behavior when you enter any valid URL in the control.

The AutoWordSelection property is set to true. This property causes the entire word to be selected if any part of the word is selected.

If set to true, the AutoWordSelection property behaves differently when you use the mouse than when you use the keyboard to make the selection. If you select a word with the mouse and extend the selection with the mouse to the next word, the entire word will be selected as soon as the first character is selected. However, if you extend the selection with the keyboard by holding down the Shift key while using the arrow key, the entire word will not be selected. Select a single character in any word with the keyboard and the entire word is not selected.

The BulletIndent and ShowSelectionMargin properties work as described in Table 12-7.

The menus are similar to those used in Example 12-1 and Example 12-2, with some additional menu items. The main menu now has File, Edit, View, and Format items. Under File, an Import command lets you import an RTF file. The Edit menu item has an additional command, CopyRtf, which allows you to copy the selected text as RTF rather than plain text. The View menu has only the Scroll To Caret command, while the Format menu is entirely new, demonstrating several of the rich text box formatting capabilities.

The menu item declarations use a different syntax in VB.NET from that in C# for assigning event handlers. A typical menu item declaration looks like:

figs/csharpicon.gif

MenuItem mnuUndo = new MenuItem("&Undo",
 new EventHandler(mnuUndo_Click),
 Shortcut.CtrlZ);

figs/vbicon.gif

dim mnuUndo as new MenuItem("&Undo", _
 new EventHandler(AddressOf mnuUndo_Click), _
 Shortcut.CtrlZ)

These menu item declarations were described briefly in conjunction with Example 12-1 and Example 12-2 and will be detailed in Chapter 18.

The File Import menu item is handled by the method mnuImport_Click. This method uses the common dialog OpenFile, described in Chapter 6. The equivalent VB.NET version of this method looks like this:

figs/vbicon.gif

private sub mnuImport_Click(ByVal sender As Object, _
 ByVal e As EventArgs)
 dim ofd as new OpenFileDialog( )
 ofd.InitialDirectory = "c:\"
 ofd.Filter = "RTF files (*.rtf)|*.rtf|" + _
 "All files (*.*)|*.*"
 ofd.FilterIndex = 1 ' 1 based index
 
 if ofd.ShowDialog( ) = DialogResult.OK then
 try
 dim reader as new StreamReader(ofd.FileName)
 rtxt.Rtf = reader.ReadToEnd( )
 reader.Close( )
 catch ex as Exception
 MessageBox.Show(ex.Message)
 return
 end try
 end if
end sub

In either language, a new OpenFileDialog is instantiated and several properties, including InitialDirectory, Filter, and FilterIndex, are set. The dialog is displayed by using the ShowDialog method. If that method returns OK, then the selected file is read into the control by using a StreamReader object. The StreamReader object required that the System.IO namespace be referenced at the beginning of the program:

figs/csharpicon.gif

using System.IO;

figs/vbicon.gif

imports System.IO

In this example, all the methods implementing the Edit commands are simpler than the equivalent methods shown in Example 12-1 and Example 12-2. The current example has only a single control that might be the target of the action, whereas the previous examples had multiple text boxes and code to determine which text box was the target. In Example 12-5, the target control is hardwired to be rtxt.

The next method of note is mnuCopyRtf_Click, which implements the Edit Copy Rtf command. This method determines whether anything is selected by testing if the SelectionLength property is greater than zero. If so, it uses the static Clipboard.SetDataObject method, passing in the SelectedRtf property as an argument. This property includes the RTF formatting codes, so if the contents are pasted into another control or application, the RTF codes are visible. This is in contrast to the Copy method used in mnuCopy_Click, which copies the selection to the Clipboard directly. If the contents of the Clipboard are pasted into Notepad, it is pasted as plain text, but if pasted into WordPad, it is pasted in with the formatting preserved. To see this concept in action, consider the instance of RichTextBoxes shown in Figure 12-4 with some formatted text entered and selected.

Figure 12-4. RichTextBox with selected text

figs/pnwa_1204.gif

If the Edit Copy Rtf command is executed and then pasted in WordPad, and then the Edit Copy command is executed on the same selection and then pasted into the same WordPad session, the WordPad session will look like Figure 12-5.

Figure 12-5. WordPad with pasted RTF selections

figs/pnwa_1205.gif

The Format menu looks like that shown in Figure 12-6. This is hardly a full-featured format menu, but it demonstrates a representative sampling of properties.

Figure 12-6. RichTextBoxes Format menu

figs/pnwa_1206.gif

Most of these menu items are simple toggles (e.g., if the selection is not bulleted, then bullet it; otherwise, unbullet it). In the case of the SelectionBullet property, which is a Boolean, a single line of code accomplishes the task:

figs/csharpicon.gif

rtxt.SelectionBullet = !rtxt.SelectionBullet;

figs/vbicon.gif

rtxt.SelectionBullet = not rtxt.SelectionBullet

The Format Red command simply toggles the selection between red and black. The code is slightly more complex:

figs/csharpicon.gif

if (rtxt.SelectionColor = = Color.Red)
 rtxt.SelectionColor = Color.Black;
 else
 rtxt.SelectionColor = Color.Red;

figs/vbicon.gif

if rtxt.SelectionColor.Equals(Color.Red) then
 rtxt.SelectionColor = Color.Black
else
 rtxt.SelectionColor = Color.Red
end if

The VB.NET version uses the Equals method rather than the = symbol because VB.NET does not support overloading of operators, except for predefined types, and Color is a class.

The Bold, Hanging Indent, Indent, and Right Indent formatting commands are similar to the Red formatting command (which tests to see if the desired property is current and sets the property accordingly).

In a real-life application, you would probably want to open the ColorDialog common dialog box and give the user a real choice.

The final formatting commands are the three Align commands: AlignLeft, AlignCenter, and AlignRight. Although these commands are not toggles, apply the appropriate property:

figs/csharpicon.gif

rtxt.SelectionAlignment = HorizontalAlignment.Center;

12.3.1 RichTextBox Methods and Events

As you would expect, the RichTextBox control has several methods and events in addition to those it inherits. Some of the most commonly used methods are listed in Table 12-11, with commonly used events listed in Table 12-16. (Tables Table 12-12 through Table 12-15 contain detailed information about the methods.)

The listing in Example 12-6 demonstrates several of the RichTextBox methods and events using C#. As with the previous example, this program is lengthy and virtually identical to the VB.NET version (aside from the normal syntactic differences). Only the C# version is presented in its entirety. Sections of code that are significantly different in VB.NET will be shown. The complete VB.NET source code can be downloaded from http://www.LibertyAssociates.com (click on Books).

Table 12-11. RichTextBox methods

Method

Description

CanPaste

Returns true if the data in the Clipboard can be pasted to the control in the specified format, false otherwise.

Find

Overloaded. Finds text within the control. If found, highlights the text and returns the zero-based index of the search result, or returns -1 if not found. The overloaded forms are listed in Table 12-12.

GetCharFromPosition

Takes a point structure as an argument. Returns the character within the control closest to that point.

GetCharIndexFromPosition

Takes a point structure as an argument. Returns the zero-based index of the character within the control closest to that point.

GetLineFromCharIndex

Takes a zero-based character index as an argument. Returns the zero-based line number containing that character.

GetPositionFromCharIndex

Takes a zero-based character index as an argument. Returns the location of that character.

LoadFile

Overloaded. Loads a text file or existing data stream into the control. The overloaded forms are listed in Table 12-14.

Paste

Overloaded. Pastes the contents of the Clipboard into the control. The overloaded form takes a DataFormats.Format as an argument, pasting an object of that format.

Redo

Reapplies the last operation that was undone.

SaveFile

Overloaded. Saves the contents of the control to a file or an existing data stream. The types of files that can be saved are contained in the RichTextBoxStreamType enumeration, listed in Table 12-15.

Table 12-12. RichTextBoxFind method overload argument list

Method

Description

char[ ]

Searches for first occurrence of a character in character array. Case sensitive.

string

Searches for string. Cannot find string if it spans more than one line in the control. Not case sensitive.

char[ ], int

Searches for first occurrence of a character in character array starting at a specified position in the control. If the starting index is zero, it searches from the beginning. Case sensitive.

string, RichTextBoxFinds

Searches for string with options specified by the bitwise combination of RichTextBoxFinds (listed in Table 12-13). Cannot find string if it spans more than one line in the control.

char[ ], int, int

Searches for first occurrence of a character in character array starting at a specified position in the control and ending at a specified position. If the starting index is zero, it searches from the beginning. If the ending index is -1, the search goes to the end. Case sensitive.

string, int, RichTextBoxFinds

Searches for string starting at a specified position in the control with options specified by the bitwise combination of RichTextBoxFinds (listed in Table 12-13). If the starting index is zero, it searches from the beginning. Cannot find string if it spans more than one line in the control.

string, int, int, RichTextBoxFinds

Searches for string starting at a specified position in the control and ending at a specified position with options specified by the bitwise combination of RichTextBoxFinds (listed in Table 12-13). If the starting index is zero, it searches from the beginning. If the ending index is -1, the search goes to the end. Cannot find string if it spans more than one line in the control.

Table 12-13. RichTextBoxFinds enumeration values

Value

Description

MatchCase

Casing must match exactly.

NoHighlight

If found, search text will not be highlighted.

None

Locate all instances, whether whole words or not.

Reverse

Start search at end and search to the beginning.

WholeWord

Locate only whole words.

Table 12-14. RichTextBox LoadFile method overload argument list

Method

Description

string

Loads the RTF file specified in the argument into the control.

stream, RichTextBoxStreamType

Loads an existing data stream into the control. The type of the data stream is specified by the RichTextBoxStreamType argument, whose legal values are listed in Table 12-15.

string, RichTextBoxStreamType

Loads file into the control. The type of the file is specified by the RichTextBoxStreamType argument, whose legal values are listed in Table 12-15.

Table 12-15. RichTextBoxStreamType enumeration values

Value

Description

PlainText

Plain ASCII text stream with no formatting. OLE objects are replaced with spaces.

RichNoOleObjects

RTF stream. OLE objects are replaced with spaces. Only valid for use with the SaveFile method.

RichText

RTF stream.

TextTextOleObjs

Plain text stream. OLE objects are replaced textual representation. Only valid for use with the SaveFile method.

UnicodePlainText

Same as PlainText, except text is encoded as Unicode.

Table 12-16. RichTextBox events

Event

Event argument

Description

HScroll

EventArgs

Raised when the horizontal scrollbar is clicked.

LinkClicked

LinkClickedEventArgs

Raised when user clicks on a link in the control. Event argument provides a LinkText property.

Protected

EventArgs

Raised when the user attempts to modify protected text. Text is protected by setting the SelectionProtected property true for selected text. The program can perform actions such as warning that this is protected text or provide a dialog for specific formatting.

SelectionChanged

EventArgs

Raised when the selection has changed.

VScroll

EventArgs

Raised when the vertical scrollbar is clicked.

Example 12-6. RichTextBox methods and events in C# (RichTextBoxMethodsEvents.cs)

figs/csharpicon.gif

using System;
using System.Drawing;
using System.Windows.Forms;
using System.IO;
 
namespace ProgrammingWinApps
{
 public class RichTextBoxMethodsEvents : Form
 {
 RichTextBox rtxt;
 string strFileName;
 
 public RichTextBoxMethodsEvents( )
 {
 Text = "RichTextBox Methods & Events";
 Size = new Size(400, 500);
 
 rtxt = new RichTextBox( );
 rtxt.Parent = this;
 rtxt.Rtf = "{\rtf1\pard Some RTF text.}";
 rtxt.Multiline = true;
 rtxt.BorderStyle = BorderStyle.Fixed3D;
 rtxt.ScrollBars = RichTextBoxScrollBars.ForcedVertical;
 rtxt.Dock = DockStyle.Fill;
 rtxt.AutoWordSelection = true;
 rtxt.BulletIndent = 10;
 rtxt.ShowSelectionMargin = true;
 rtxt.LinkClicked += new LinkClickedEventHandler(Link_Click);
 rtxt.SelectionChanged += new EventHandler(Selection_Changed);
 
 // Menus
 // File menu items
 MenuItem mnuImport = new MenuItem("&Import...",
 new EventHandler(mnuImport_Click),
 Shortcut.CtrlI);
 MenuItem mnuLoad = new MenuItem("&Load...",
 new EventHandler(mnuLoad_Click),
 Shortcut.CtrlL);
 MenuItem mnuSaveAs = new MenuItem("Save &As...",
 new EventHandler(mnuSaveAs_Click));
 MenuItem mnuFile = new MenuItem("&File",
 new MenuItem[ ] {mnuImport, mnuLoad, mnuSaveAs});
 
 // Edit menu items
 MenuItem mnuFind = new MenuItem("&Find",
 new EventHandler(mnuFind_Click),
 Shortcut.CtrlF);
 MenuItem mnuRedo = new MenuItem("&Redo",
 new EventHandler(mnuRedo_Click));
 MenuItem mnuEdit = new MenuItem("&Edit",
 new MenuItem[ ] {mnuFind, mnuRedo});
 
 // Main menu
 Menu = new MainMenu(new MenuItem[ ] {mnuFile, mnuEdit});
 
 } // close for constructor
 
 static void Main( ) 
 {
 Application.Run(new RichTextBoxMethodsEvents( ));
 }
 
 private void mnuImport_Click(object sender, EventArgs e)
 {
 OpenFileDialog ofd = new OpenFileDialog( );
 ofd.InitialDirectory = @"c:";
 ofd.Filter = "RTF files (*.rtf)|*.rtf|" +
 "All files (*.*)|*.*";
 ofd.FilterIndex = 1; // 1 based index
 
 if (ofd.ShowDialog( ) = = DialogResult.OK)
 {
 try
 {
 StreamReader reader = new StreamReader(ofd.FileName);
 rtxt.Rtf = reader.ReadToEnd( );
 reader.Close( );
 }
 catch (Exception ex)
 {
 MessageBox.Show(ex.Message);
 return;
 }
 }
 }
 
 private void mnuLoad_Click(object sender, EventArgs e)
 {
 OpenFileDialog ofd = new OpenFileDialog( );
 ofd.InitialDirectory = @"c:";
 ofd.Filter = "RTF files (*.rtf)|*.rtf|" +
 "Text files (*.txt)|*.txt|" +
 "All files (*.*)|*.*";
 ofd.FilterIndex = 1; // 1 based index
 
 if (ofd.ShowDialog( ) = = DialogResult.OK)
 {
 try
 {
 // Determine the file extension
 if (ofd.FileName.EndsWith(".rtf"))
 rtxt.LoadFile(ofd.FileName);
 else 
 {
 if (ofd.FileName.EndsWith(".txt"))
 rtxt.LoadFile(ofd.FileName, 
 RichTextBoxStreamType.PlainText);
 else
 MessageBox.Show("Invalid file format.");
 }
 }
 catch (Exception ex)
 {
 MessageBox.Show(ex.Message);
 return;
 }
 }
 }
 
 private void mnuSaveAs_Click(object sender, EventArgs e)
 {
 SaveFileDialog sfd = new SaveFileDialog( );
 sfd.InitialDirectory = @"c:";
 sfd.Filter = "RTF files (*.rtf)|*.rtf|" +
 "Text files (*.txt)|*.txt|" +
 "All files (*.*)|*.*";
 sfd.FilterIndex = 1; // 1 based index
 
 if (strFileName != null)
 sfd.FileName = strFileName;
 else
 sfd.FileName = "*.rtf";
 
 if (sfd.ShowDialog( ) = = DialogResult.OK)
 {
 try
 {
 strFileName = sfd.FileName;
 
 // Determine the file extension
 if (strFileName.EndsWith(".rtf"))
 rtxt.SaveFile(strFileName);
 else 
 {
 if (strFileName.EndsWith(".txt"))
 rtxt.SaveFile(strFileName, 
 RichTextBoxStreamType.PlainText);
 else
 MessageBox.Show("Invalid file format.");
 }
 }
 catch(Exception ex)
 {
 MessageBox.Show(ex.Message);
 return;
 }
 }
 }
 
 private void mnuFind_Click(object sender, EventArgs e)
 {
 // use the current selection as the string to find.
 if (rtxt.SelectionLength > 0)
 {
 string str = rtxt.SelectedText;
 int intStart = rtxt.Find(str, 
 rtxt.SelectionStart + rtxt.SelectionLength, 
 -1, RichTextBoxFinds.None); 
 if (intStart < 0)
 MessageBox.Show("String not found.");
 }
 else
 MessageBox.Show("Nothing to find.");
 }
 
 private void mnuRedo_Click(object sender, EventArgs e)
 {
 if (rtxt.CanRedo)
 rtxt.Redo( );
 }
 
 private void Link_Click(object sender, LinkClickedEventArgs e)
 {
 System.Diagnostics.Process.Start(e.LinkText);
 }
 
 private void Selection_Changed(object sender, EventArgs e)
 {
 if (rtxt.SelectionLength > 0)
 MessageBox.Show("You have changed the selection to "" +
 rtxt.SelectedText + """);
 }
 
 } // close for form class
} // close form namespace

When the program listed in Example 12-6 is compiled and run, it looks similar to that shown for the previous example in Figure 12-3, except that the menu is sparser and there is no horizontal scrollbar.

The code in Example 12-6 is similar to that listed in Example 12-5.

The constructor has two lines that add two event handlers for LinkClicked and SelectionChanged events, respectively:

figs/csharpicon.gif

rtxt.LinkClicked += new LinkClickedEventHandler(Link_Click);
rtxt.SelectionChanged += new EventHandler(Selection_Changed);

figs/vbicon.gif

AddHandler rtxt.LinkClicked, AddressOf Link_Click
AddHandler rtxt.SelectionChanged, AddressOf Selection_Changed

The menu is significantly trimmed down, with only File and Edit top-level menu items, and fewer menu items overall.

As before, most action occurs in the event handler methods. The event handler for importing an RTF file, mnuImport_Click, is unchanged from the previous example. It is left in here simply as a comparison with the Load menu item. The handler for that item, mnuLoad_Click, uses the same OpenFileDialog common dialog, but rather than use a StreamReader to stream the file into the Rtf property of the control, it uses the LoadFile instance method.

Another difference between the Import and Load event handlers is that the Load event handler allows both RTF and text files, reflected in the OpenFileDialog Filter property:

figs/csharpicon.gif

ofd.Filter = "RTF files (*.rtf)|*.rtf|" +
 "Text files (*.txt)|*.txt|" +
 "All files (*.*)|*.*";

Then within the try block where the selected file is actually loaded, the string EndsWith instance method determines if the selected file is an RTF or a TXT file. If it is the former, the LoadFile method is invoked with only the filename as an argument. If it is the latter, then the LoadFile method is invoked with RichTextBoxStreamType.PlainText passed as an argument:

figs/csharpicon.gif

try
{
 // Determine the file extension
 if (ofd.FileName.EndsWith(".rtf"))
 rtxt.LoadFile(ofd.FileName);
 else 
 {
 if (ofd.FileName.EndsWith(".txt"))
 rtxt.LoadFile(ofd.FileName, 
 RichTextBoxStreamType.PlainText);
 else
 MessageBox.Show("Invalid file format.");
 }
}
catch (Exception ex)
{
 MessageBox.Show(ex.Message);
 return;
}

figs/vbicon.gif

try
 ' Determine the file extension
 if ofd.FileName.EndsWith(".rtf") then
 rtxt.LoadFile(ofd.FileName)
 else 
 if (ofd.FileName.EndsWith(".txt"))
 rtxt.LoadFile(ofd.FileName, RichTextBoxStreamType.PlainText)
 else
 MessageBox.Show("Invalid file format.")
 end if
 end if
catch ex as Exception
 MessageBox.Show(ex.Message)
 return
end try

The File Save As command is implemented in the mnuSaveAs_Click event handler method. This is analogous to the Load event handler, except that it uses the SaveFileDialog common dialog box and invokes the SaveFile method rather than the LoadFile method. As with the Load event handler, it tests the extension of the specified filename to determine if the file should be saved as RTF or a plain text file, using the same arguments as the LoadFile method.

Most real-world applications implement a Find function by presenting a dialog box for the user to enter the search string. The Edit Find command implemented in this example forgoes the dialog box and uses the current selection as the search string. If nothing is selected, as determined by testing the SelectionLength property, then the Find method is not invoked.

Assuming there is something selected, the selected text is assigned to a string variable, which is then passed to the Find method, along with several other arguments. Seven overloaded forms of the Find method are listed in Table 12-12, providing the ability to search for either a character or a string, either in the entire control or in a specified range. If it is a string, it uses a combination of RichTextBoxFinds enumeration values, listed in Table 12-13, to refine the search.

In any case, if the search is successful, the Find method returns the zero-based index of the first character of the string that is found. It also highlights the found string. If nothing is found, then the method returns -1.

In this example, four arguments are passed to the Find method: the search string, the starting index, the ending index, and a RichTextBoxFinds enumeration value:

figs/csharpicon.gif

int intStart = rtxt.Find(str,
 rtxt.SelectionStart + rtxt.SelectionLength, 
 -1, RichTextBoxFinds.None);

figs/vbicon.gif

dim intStart as integer = rtxt.Find(str, _
 rtxt.SelectionStart + rtxt.SelectionLength, _
 -1, RichTextBoxFinds.None)

Notice that the starting index is set to the index at the start of the selection plus the length of the selection, which effectively starts the search at the end of the selection. If you started the search at the start of the selection, it would just find itself.

The ending index is set to -1, which has the effect of searching to the end of the control contents. The following line would be equivalent to the line used:

figs/csharpicon.gif

int intStart = rtxt.Find(str,
 rtxt.SelectionStart + rtxt.SelectionLength, 
 RichTextBoxFinds.None);

Since none of the overloaded forms of the method allows searching for a string from a specified starting point without passing a RichTextBoxFinds parameter, even if there is no refinement to the desired search, the None enumerated value is passed in.

If the search is successful, the found text is highlighted and the character index of the first character of the found string is assigned to the integer intStart. If nothing is found, then -1 would be returned. intStart is tested and if it is negative, a message is displayed.

The Edit Redo menu item demonstrates the Redo method as invoked in the mnuRedo_Click event handler. It first tests the CanRedo property to see if there is anything to redo. If so, the Redo method is called. This has the effect of reversing the previous Undo operation.

The Redo command assumes that you have first called Undo to reverse an operation. However, this example does not have an explicit Undo command. The Cut, Copy, Paste, Select All, and Undo commands all work as part of the default behavior of TextBoxBase controls.

Two event handlers in Example 12-6 are not associated with any menu item.

The Link_Click event handler is invoked whenever a URL in the control is clicked. This event handler was assigned to the LinkClicked event back in the constructor with the following line:

figs/csharpicon.gif

rtxt.LinkClicked += new LinkClickedEventHandler(Link_Click);

figs/vbicon.gif

AddHandler rtxt.LinkClicked, AddressOf Link_Click

This event passes an event argument of type LinkClickedEventArgs, which contains the text of the URL that was clicked. This text is then passed as an argument to the Process.Start method of the System.Diagnostics namespace, which starts an instance of the default application for the passed-in link text, which depends on the link. For example, if the link text is www.LibertyAssociates.com, then a browser will be opened and navigate to that web site. If the link text is file:c: est.txt, then that file will be opened in Notepad.

The SelectionChanged event is raised every time the selection is changed in the text box. It is assigned to the Selection_Changed event handler method with the appropriate line of code.

figs/csharpicon.gif

rtxt.SelectionChanged += new EventHandler(Selection_Changed);

figs/vbicon.gif

AddHandler rtxt.SelectionChanged, AddressOf Selection_Changed

The Selection_Changed event handler first tests to see if anything is selected (i.e., the selection length is greater than zero) to prevent the message box from popping up every time you deselect. Anything that is selected is displayed in a message box.

Windows Forms and the .NET Framework

Getting Started

Visual Studio .NET

Events

Windows Forms

Dialog Boxes

Controls: The Base Class

Mouse Interaction

Text and Fonts

Drawing and GDI+

Labels and Buttons

Text Controls

Other Basic Controls

TreeView and ListView

List Controls

Date and Time Controls

Custom Controls

Menus and Bars

ADO.NET

Updating ADO.NET

Exceptions and Debugging

Configuration and Deployment



Programming. NET Windows Applications
Programming .Net Windows Applications
ISBN: 0596003218
EAN: 2147483647
Year: 2003
Pages: 148

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net