Click here to Skip to main content
13,408,783 members (45,128 online)
Click here to Skip to main content
Add your own
alternative version


42 bookmarked
Posted 23 Jan 2015

EXTENDED Version of Extended Rich Text Box (RichTextBoxEx)

, 31 Jan 2018
Rate this:
Please Sign up or sign in to vote.
I've created an enhanced version of the Extended RichTextBox created by Razi Syed.

The RichTextBox of Visual Studio allows a lot of things; the problem is, a host program has to initiate those things in code. The following control, RichTextBoxEx, which features a toolbar and ruler, allows elaborate end-user-initiated functionality in a single WinForms control. Below is the RichTextBoxEx control, plus CheckBoxes to enable/disable spell-check and picture insertion and a multi-line TextBox to show the main control's width, scroll position, and character code for any selected text.


This UserControl is a WinForms RichTextBox with a Toolstrip and Ruler added to allow the user to do the following things with it (some updates are recent--as of February 2018):

  1. Setting  (foreground and background),  attributes, text alignment, and text bulleting
  2. Finding and replacing search text
  3. Spell-checking
  4. Picture-inserting
  5. Hyphenation/dehyphenation
  6. Defining custom characters and smart-character conversions
  7. Saving and loading text
  8. Printing (using class library)
  9. Tracking scroll-bar information (using class library)
  10. Keeping track of whether recent changes have been made
  11. Setting tabs indents and tabs via a ruler

This tip features the RichTextBoxEx control--an enhanced version of the "Extended RichTextBox" created by Razi Syed--along with Paul Welter's "NetSpell - Spell Checker for .NET" - plus a class library for printing rich text and getting scroll-bar info (standard or enhanced control), a ruler control specially designed for rich-text boxes, and a small demo program. This version has last been updated on February 1, 2018.


This version of RichTextBoxEx has the following enhancements to Razi Syed's version:

  1. Buttons for Background Color, Italic, Insert Picture, Find/Replace, Find Next, and Hyphenate--and combo boxes for  face and size--have been added to the toolstrip. Also, when the control is resized, the constituent controls--toolstrip and text box--are resized to fill it.
  2. The underlying RichTextBox, "rtb", is declared Public so that its properties, methods, and events can be accessed; just be sure to include "rtb" in the object expression (NOTE: UseAddHandler/RemoveHandler to catch events; WithEvents/Handles don't work with a UserControl's constituent controls.)
  3. The underlying "rtb" control has its AllowDrop property set to True, so that rich text can easily be dragged and dropped back and forth with other rich-text apps.HideSelection is set to False so selected text can be viewed while find, replace, and hyphenation dialogs are showing. ShowSelectionMargin is set to True so that the user can easily select whole lines of text.
  4. A context menu with shortcut keys is assigned to the "rtb" control.
  5. The constituent rich-text control's internal KeyDown event defines several "custom characters"--and raises an event to allow you to define your own custom characters or shortcuts; its internal KeyPress event defines "smart characters"--and raises an event to allow you to define your own smart-character replacements.
  6. There are top-level properties for allowing/disallowing spell-check/bullets/picture-insertion/insert-text/smart-text by the user, showing/hiding the toolstrip (items' shortcut keys and any custom characters still work), allow/disallow setting text  and  together--and, as previously mentioned, an event to allow custom key sequences to generate RTF characters/strings.
  7. To search for text, use Find/Replace (Ctrl + F / Ctrl + H) to pull up a dialog box for entering search text, search direction (up or down), and whether or not to make search case-sensitive and/or whole word. If found in the rich-text, the word is selected. If opting to replace, you can replace one occurrence or all occurrences from the current position in the specified direction. To exit the Find or Replace dialog, hit Cancel (ESC). To find and select subsequent occurrences of the same text (using the same direction and criteria), use Find Next (F3).
  8. Pictures can be added. When the Insert Picture button (or the equivalent context-menu item) is selected, a file dialog allows the user to select a picture file. The picture is copied to the clipboard and pasted into the control at the current caret position (replacing any pre-highlighted text).
  9. The control can search for hyphenateable wrapped text; when such a word is found, a dialog box allows one to position the breaking point, and either hyphenate the word, skip it (leave it alone), or quit. (The word must be a series of alphanumeric characters with enough length/space to leave 2+ characters at the end of the first line and 3+ characters at the beginning of the second line after breaking.)
  10. The control can dehyphenate text: The options to hyphenate text, remove all hyphens, or remove only "hidden" hyphens (hyphens not displayed because text doesn't wrap after them) are in the "Hyphenate" context menu.
  11. A class library is added to facilitate printing of rich text, and tracking of the text box's scroll-bar info. The first 5 extension methods can be used to find page breaks within the text box, and to print or preview one, some, or all pages; the other 3 methods can be used to get or set the scroll-bars' positions or retrieve detailed information about either scroll bar.
  12. Three methods are created: 1 for saving RTF text, 1 for loading RTF text, and 1 for inserting pictures
  13. A ruler can be displayed to allow the user to set first-line/hanging/right indents and tabs.

Using the Code

Control's Reference Dependencies

To use the RichTextBoxEx user control in a project/solution, you must reference not only RichTextBoxEx.dll, but also PrintRichTextBox.dll, NetSpell.SpellChecker.dll, and TextRuler.dll--as RichTExtBoxEx uses all three auxiliary libraries. Each of these supporting libraries can be used on their own; to find out how to use the TextRuler, see the article General-purpose RULER Control for Use with RICH-TEXT CONTROLS by yours truly.

Properties for RichTextBoxEx

  • MaintainSelection -- Boolean for whether highlighting should be restored to selected text after a replace, hyphenation, or spell-check operation
  • IsTextChanged --Boolean for whether text has been changed since it was saved, loaded, or last set to False (set to True to assume changes, False to indicate no recent changes). It is similar to the underlying rich-text box's Modfied property except that it is set to True, and the ChangesMade event is fired,when the Text property is set (or Rtf's value is changed), and not when "temporary" changes (like trial hyphenations) are made.
  • SetColorWithFont -- Boolean for whether it should be possible to set text  from within the Font dialog
  • ShowToolstrip -- Boolean for whether to show Toolstrip on top of RichTextBox
  • ShowRuler -- Boolean for whether to show a ruler for setting indents and tabs
  • AllowTabs -- Boolean for whether the user is able to set tabs for paragraphs (only meaningful if ShowRuler is True)
  • AllowSpellCheck -- Boolean for whether control should provide for spell-checking
  • AllowDefaultInsertText -- Boolean for whether control should provide automatic default custom-character insertions along with any user-defined ones
  • AllowDefaultSmartText -- Boolean for whether control should provide automatic default smart-character replacments along with any user-defined ones
  • AllowBullets -- Boolean for whether control should allow list bulleting
  • AllowHyphenation -- Boolean for whether control should support hyphenation searches
  • AllowPictures -- Boolean for whether control should allow pictures to be inserted
  • UnitsForRuler -- TextRuler.Units enumeration for whether Inches or Centimeters should be used for the ruler (Import TextRulerControl)
  • RightMargin  -- maximum printable width (rtb.RightMargin) for text; the ruler display is updated to reflect the change
  • FilePath -- String for directory the file dialog should start with (when saving text, loading text, or inserting pictures)
  • rtb -- constituent RichTextBox control
  • Text -- String for plain-text contents of text box (rtb.Text); IsTextChanged and rtb.Modified are set to True and ChangesMade event is fired always
  • Rtf -- String for RTF contents of text box (rtb.Rtf); IsTextChanged and rtb.Modified are set, and ChangesMade is fired, only if new value is different from existing value

Methods for RichTextBoxEx

  • booleanvalueSaveFile([filename]) -- saves context of rich-text box to an RTF-format file. If filename is null or omitted, then a file dialog is invoked with FilePath as the initial directory. Returns True if text was saved, False if dialog was canceled. Sets IsTextChanged to False if successful.
  • booleanvalue = LoadFile([filename]) -- loads the contents of an RTF-format file into the rich-text box. If filename is null or omitted, then a file dialog is invoked with FilePath as the initial directory. Returns True if text was loaded, False if dialog was canceled. Sets IsTextChanged to False if successful.
  • booleanvalue = InsertPicture([filename]) -- inserts a picture into the rich-text box at the caret (in place of any selected text). If filename is null or omitted, then a file dialog is invoked with FilePath as the initial directory. Returns True if picture was inserted, False if dialog was canceled. Sets IsTextChanged to True, and fires ChangesMade event, if successful.

Events for RichTextBoxEx

InsertRtfText -- allows host program to define custom (RTF) characters or functionality for various keystrokes.

  • INPUT:
    • e.KeyEventArgs -- information about keys being pressed (from "rtb"'s underlying KeyDown event)
    • e.RtfText -- custom text to be inserted (or replaced over selected text); format is RTF so that program can add functions and characters that are supported by the text box only through RTF codes (as opposed to properties and methods)

SmartRtfText -- allows host program to define smart (RTF) character-replacements for raw "dumb characters" as they are typed in.

  • INPUT:
    • e.KeyPressEventArgs -- information about keys being pressed (from "rtb"'s underlying KeyPress event)
    • e.RtfText -- custom text to be take the place of the incoming character, and possibly immediately preceding characters before the caret; format is RTF so that program can add functions and characters that are supported by the text box only through RTF codes (as opposed to properties and methods);
    • e.PrecedingCharacterCount -- number of existing characters, precedding the incoming character, which are to be removed before adding smart character(s).

ChangesMade -- fires when changes are made to contents of rich-text box; it differs from rtb_TextChanged in that it doesn't fire when "temporary" changes--like when the control does trial hyphenation in order to figure where hyphens can be inserted--take place. IsTextChanged will always be True when this event fires.

Extension Methods for PrintRichTextBox

NOTE: These methods are designed work for a standard RichTextBox, so that they work even if you're not using the RichTextBoxEx control. (When using the RichTextBoxEx control, use its rtb property to reference the underlying RichTextBox. Don't forget to Import PrintRichTextBox!)

Extension methods for printout:

  • richtextbox.Print(PrintDocument) -- prints text. The PrinterSettings.PrintRange property of the PrintDocument instance determines whether the current page (at the caret), pages with selected text, a range of pages, or the entire text is printed.
  • dialogresult = richtextbox.PrintPreview(PrintPreviewDialog) -- previews text. What's previewed depends, once again, on the PrinterSettings.PrintRange property of the PrintDocument assigned to the dialog.
  • integerarray() = richtextbox.PageIndexes(PrintDocument) -- returns an array with the start positions within the text box for each successive page. This can be used to determine what text would be printed on what page.
  • richtextBox.SetRightMarginToPageWidth(PageSettings) -- sets richtextbox.RightMargin property so that text box wraps text at the same horizontal position as the printed page's width (within left and right margins). This method always sets control's WordWrap property to False.
  • richtextbox.SetPageWidthToRightMargin(PageSettings) -- sets printed page's right margin so that it wraps text at the same horizontal position as indicated by richtextbox.RightMargin property. This is SetRightMarginToPageWidth in reverse. If the RightMargin property is 0, then no changes are made.

Extension methods for tracking scroll bars:

  • scrollposition = richtextbox.GetScrollPosition() -- gets current horizontal and vertical scroll-bar positions in pixels to a System.Drawing.Point structure.
  • richtextbox.SetScrollPosition(scrollposition) -- sets the horizontal and vertical scroll-bars to pixel positions specified in a System.Drawing.Point structure.
  • scrollinfo = richtextbox.GetScrollBarInfo(type[, mask]) -- returns the range, page-size, position, and/or track-position info about a scroll bar to a PrintRichTextBox.ScrollInfo structure. type is a PrintRichTextBox.ScrollBarType enum value specifying Horizontal or Vertical; mask is an optional bit-flag PrintRichTextBox.ScrollBarMask enum value specifying what parameters to retrieve (by default, all 4 items).
  • textwidth = richtextbox.GetMaximumWidth() -- gets maximum horizontal width in pixels for any text. If control's RightMargin property is non-zero, then that is used; otherwise, if WordWrap is True, then control's client-area width is used; otherwise, the width of the widest line in the text is used. It also accounts for whether ShowSelectionMargin is True or False.

A few code examples are given below:

Imports RichTextBoxEx
Imports PrintRichTextBox
Imports TextRulerControl

'   using a property or method

RichTextBoxEx1.AllowSpellCheck = True : RichTextBoxEx1.UnitsForRuler = TextRuler.Inches

RichTextBoxEx1.SaveFile("My Text.rtf")

'   using extension methods on underlying text box

Dim ScrollPosition As Point = RichTextBoxEx1.rtb.GetScrollPosition()



Dim Pages() As Integer = RichTextBoxEx1.rtb.PageIndexes(PrintDocument1)

RichTextBoxEx1.rtb.Select(Pages(2), Pages(3) - Pages(2)) ' select a page

'    catching events

AddHandler RichTextBoxEx1_InsertRtfText, RichTextBoxEx1.InsertRtfText

AddHandler RTB_DoubleClick, RichTextBoxEx1.rtb.DoubleClick ' event for underlying text box

Shortcut keys are keystroke-defined similar to Word. For instance, Ctrl+X is Cut, Ctrl + I is Italic, Ctrl + F is Find, Ctrl + H is Replace, F3 is Find Next, F7 is Spell-Check, etc. Simply click on the control's constituent component, ContextMenuStrip1, to see them all. (At run time, the menus can, of course, be invoked by right-clicking the text box. If the ruler is shown, then the user can switch between inches and centimeters by right-clicking the ruler in order to show its menu,)

As for the pre-defined custom characters, here is the list of keystrokes:


Key Sequence

Optional (syllable) hyphen
(- ; displays only when breaking
a word at the end of a line)

[Ctrl] + [-]

Em dash (—)

[Ctrl] + [Alt] + [-]

Left single quote (‘)

[Ctrl] + [`]

Left double quote (“)

[Ctrl] + [Shift] + [~]

Right single quote (’)

[Ctrl] + [']

Right double quote (”)

[Ctrl] + [Shift] + ["]

Copyright (©)

[Ctrl] + [Alt] + [C]

Registered trademark (®)

[Ctrl] + [Alt] + [R]

Trademark (™)

[Ctrl] + [Alt] + [T]



As for default smart-character conversions:

  1. A regular double quote ("), when typed, is changed to a left double quote (“) if tit occurs at the beginning of a line, or after a space, regular dash, em dash, tab, or left single quote; otherwise it is changed to a right double quote (”).
  2. A regular single quote ('), when typed, is changed to a left single quote (‘) if it occurs at the beginning of a line, or after a space, regular dash, em dash, tab, or left double quote; otherwise it is changed to a right single quote (’).
  3. A regular dash (-), when typed immediately after an existing regular dash is replaced (along with its preceding dash) with an em dash (—).

Demo Program

Features include the following:

  1. A Page Setup Dialog--invoked at the beginning of the program--to allow page size and margins to be set.
  2. Check boxes to enable/disable Spell-Check and Insert-Picture for the RichTextBoxEx control
  3. Displaying the UTF-32 Unicode values for the characters of the RichTextBoxEx's selected text in a (vertically-scrollable) standard TextBox--useful for determining which character codes do what in a RichTextBox--and showing the text box's current scroll position.
  4. Invoking the Print Dialog, followed by Print Preview and Print, when the text box is double-clicked or [Ctrl] + [P] is pressed.
  5. Saving or loading the text when [Ctrl] + [S] or [Ctrl] + [O], respectively, are pressed. Also, when exiting the application, the user is given the option to save text if it's been modified.
  6. The following custom characters (in addition to the default ones above):


Key Sequence

One-fourth (¼)

[Ctrl] + [4]

One-half (½)

[Ctrl] + [2]

Three-fourths (¾)

[Ctrl] + [3]

Start new page (RTF code: \page ;
displays in text box only as carriage return,
but will affect printout of pages)

[Ctrl] + [Shift] + [Enter]

Save text

[Ctrl] + [S]

Load (open) text

[Ctrl] + [O]



It also now converts "1/4", "1/2", "3/4"--when they are typed in--into "¼", "½", and "¾", respectively.

Points of Interest

  1. A word about the hyphenation and spell-checker tools: They regard all optional/syllable hyphens--visible and invisible alike--as word separators. Therefore, if text is already hyphenated, they may confuse part of a word for a whole word. One solution is to dehyphenate the selected text (using the context menu), do the spell-check, then re-hyphenate it (using the button or context menu). (Another is going to the "NetSpell" article with the spell-check utility and modifying it to handle hyphenated words [hyphen character: ChrW(173)]. It could also then be designed to "auto-hyphenate" known words.)
  2. The Find, Replace, and Hyphenate dialog boxes are implemented modally, so as to have greater control over any selected text and to simplify my coding. (Hit Cancel ([ESC]) to exit find or replace dialog, or to exit hyphenation early.) The scope of text subject to search/modification for these features--and Spell-check--is the whole text unless a region of text is highlighted, in which case only the selected text is worked with. Replace, Hyphenation, and Spell-check restore the highlighting if MaintainSelection is True; Find (and find/replace if the last operation is a simple find) does not. Invoking Find through Ctrl + F displays a "find only" dialog (no replacement options). Finally, Find Next (F3) is not limited in scope to highlighted text; it looks through the full text for a subsequent occurrence.
  3. I recently add a ruler-bar to the control, the link to the article explaining it is above in the part about "dependencies".


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Robert Gustafson
United States United States
No Biography provided

You may also be interested in...

Comments and Discussions

QuestionIs it just me ...!? Pin
Member 80348605-Feb-18 22:27
memberMember 80348605-Feb-18 22:27 
GeneralMy vote of 5 Pin
Member 1236439020-Dec-17 1:26
memberMember 1236439020-Dec-17 1:26 
QuestionSuggestion Pin
Gary Strunk19-Dec-17 15:42
memberGary Strunk19-Dec-17 15:42 
GeneralMy vote of 5 Pin
BillWoodruff30-Nov-17 7:53
mvpBillWoodruff30-Nov-17 7:53 
QuestionSigned version Pin
MeziLu17-Aug-16 15:58
memberMeziLu17-Aug-16 15:58 
AnswerRe: Signed version Pin
Robert Gustafson3-Dec-17 14:04
memberRobert Gustafson3-Dec-17 14:04 
GeneralRe: Signed version Pin
MeziLu4-Dec-17 6:08
memberMeziLu4-Dec-17 6:08 
QuestionError: Index outside the bounds of the array Pin
Member 1254159430-Jun-16 22:15
memberMember 1254159430-Jun-16 22:15 
AnswerRe: Error: Index outside the bounds of the array Pin
Robert Gustafson28-Dec-17 15:38
memberRobert Gustafson28-Dec-17 15:38 
QuestionAdding Ruler Pin
Jorge_Mpj24-Jun-16 5:25
memberJorge_Mpj24-Jun-16 5:25 
AnswerRe: Adding Ruler Pin
Robert Gustafson24-Jun-16 12:24
memberRobert Gustafson24-Jun-16 12:24 
PraiseGreat control Pin
Member 1210083123-Nov-15 8:37
memberMember 1210083123-Nov-15 8:37 
GeneralRe: Great control Pin
Robert Gustafson9-Jan-16 18:30
memberRobert Gustafson9-Jan-16 18:30 
GeneralRe: Great control Pin
BillWoodruff6-Dec-17 8:38
mvpBillWoodruff6-Dec-17 8:38 
GeneralRe: Great control Pin
Robert Gustafson6-Dec-17 15:30
memberRobert Gustafson6-Dec-17 15:30 
SuggestionAdding sections Pin
Member 1112739425-Jul-15 17:59
memberMember 1112739425-Jul-15 17:59 
GeneralRe: Adding sections Pin
Robert Gustafson8-Aug-15 17:44
memberRobert Gustafson8-Aug-15 17:44 
QuestionSuggestions Pin
Jerry2016-May-15 16:58
memberJerry2016-May-15 16:58 
AnswerRe: Suggestions Pin
Robert Gustafson17-May-15 17:34
memberRobert Gustafson17-May-15 17:34 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.180221.1 | Last Updated 1 Feb 2018
Article Copyright 2015 by Robert Gustafson
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid