Rich Text Editor

In this tutorial you will create a Rich Text Editor using an extended version of the Rich Text Box Component to support Printing, also included Open and Save Support plus Formatting like Highlight and Bold, Italics and Underline.

www.cespage.com/vb/vb08tut14.html

Step 1

Start Microsoft Visual Basic 2008 Express Edition, then select File then New Project... Choose Windows Forms Application from the New Project Window, enter a name for the Project and then click OK, see below:

New Project

Step 2

A Blank Form named Form1 should then appear, see below:

Form1

Step 3

With Form1 selected goto the Properties box and change the Name from Form1 to frmMain

Form1 Properties

Step 4

Then select Project then Add Class... and choose the "Class" Template if it is not already selected and give it the Name "RichTextBoxPrint.vb" without the quotes, see below:

RichTextBoxPrint Class

Step 5

With the empty RichTextBoxPrint Class displayed, if not double click on the "RichTextBoxPrint.vb" item in Solution Explorer, then enter the following above the Public Class RichTextBoxPrint line:

Imports System.Drawing.Printing
Imports System.Runtime.InteropServices 

Enter the following below the Public Class RichTextBoxPrint:

Inherits RichTextBox

' Private Constants

Private Const AnInch As Double = 14.4 ' Convert .NET Units to Win32 API Units
Private Const WM_USER As Integer = &H400
Private Const EM_FORMATRANGE As Integer = WM_USER + 57

' API Structures and Method

<StructLayout(LayoutKind.Sequential)> _
Private Structure RECT
  Public Left As Integer
  Public Top As Integer
  Public Right As Integer
  Public Bottom As Integer
End Structure
<StructLayout(LayoutKind.Sequential)> _
Private Structure CHARRANGE
  Public cpMin As Integer ' First character of range (0 for start of doc)
  Public cpMax As Integer ' Last character of range (-1 for end of doc)
End Structure
<StructLayout(LayoutKind.Sequential)> _
Private Structure FORMATRANGE
  Public hdc As IntPtr ' Actual Device Context to draw on
  Public hdcTarget As IntPtr ' Target DC for text formatting
  Public rc As RECT ' Region of the DC to draw to in twips
  Public rcPage As RECT ' Region of the whole DC (page size) in twips
  Public chrg As CHARRANGE ' Range of text to draw
End Structure

Private Declare Function SendMessage Lib "USER32" Alias "SendMessageA" _
(ByVal hWnd As IntPtr, ByVal msg As Integer, _
 ByVal wp As IntPtr, ByVal lp As IntPtr) As IntPtr
 
' Private and Public Members
 
Private checkPrint As Integer = 0 ' Check Print Value
Public WithEvents PrintDocument As New PrintDocument ' Printer Document

See Below:

RichTextBoxPrint Imports and API Declarations

Step 6

With the RichTextBoxPrint Class still displayed, enter the following Function above "End Class" and below the "Private and Public Members" Section:

' Name    : Print
' Params  : charFrom as Integer, charTo as Integer, e as PrintPageEventArg
' Returns : Print as Integer
' Desc    : Produce RichTextBox Printable Output
Private Function Print(ByVal charFrom As Integer, ByVal charTo As Integer, _
                       ByVal e As PrintPageEventArgs) As Integer
  Dim cRange As CHARRANGE
  Dim rectToPrint As RECT
  Dim rectPage As RECT
  Dim hdc As IntPtr = e.Graphics.GetHdc()
  Dim fmtRange As FORMATRANGE
  Dim res As IntPtr = IntPtr.Zero
  Dim wparam As IntPtr = IntPtr.Zero
  Dim lparam As IntPtr = IntPtr.Zero
  ' Mark start and end character
  cRange.cpMin = charFrom
  cRange.cpMax = charTo
  ' Calculate the area to render and print
  rectToPrint.Top = CInt(e.MarginBounds.Top * AnInch)
  rectToPrint.Bottom = CInt(e.MarginBounds.Bottom * AnInch)
  rectToPrint.Left = CInt(e.MarginBounds.Left * AnInch)
  rectToPrint.Right = CInt(e.MarginBounds.Right * AnInch)
  ' Calculate the size of the page
  rectPage.Top = CInt(e.PageBounds.Top * AnInch)
  rectPage.Bottom = CInt(e.PageBounds.Bottom * AnInch)
  rectPage.Left = CInt(e.PageBounds.Left * AnInch)
  rectPage.Right = CInt(e.PageBounds.Right * AnInch)
  ' Format Range
  fmtRange.chrg = cRange ' Character from to character to 
  fmtRange.hdc = hdc  ' Same device context for measuring and rendering
  fmtRange.hdcTarget = hdc ' Point at printer hDC
  fmtRange.rc = rectToPrint ' Area on page to print
  fmtRange.rcPage = rectPage ' Whole size of page
  ' API
  wparam = New IntPtr(1)
  lparam = Marshal.AllocCoTaskMem(Marshal.SizeOf(fmtRange))
  Marshal.StructureToPtr(fmtRange, lparam, False)
  res = SendMessage(Handle, EM_FORMATRANGE, wparam, lparam) ' Print Rendered Data
  Marshal.FreeCoTaskMem(lparam) ' Free block of memory allocated
  e.Graphics.ReleaseHdc(hdc) ' Release device context handle
  Return res.ToInt32() ' Return last + 1 character
End Function

See Below:

RichTextBoxPrint Print Function

Step 7

Finally in the RichTextBoxPrint Class enter the following Event handlers above "End Class" and below the Print(...) Function:

Private Sub PrintDocument_BeginPrint(ByVal sender As Object, _
                            ByVal e As System.Drawing.Printing.PrintEventArgs) _
                            Handles PrintDocument.BeginPrint
  checkPrint = 0
End Sub

Private Sub PrintDocument_PrintPage(ByVal sender As Object, _
                               ByVal e As System.Drawing.Printing.PrintPageEventArgs) _
                               Handles PrintDocument.PrintPage
  ' Print the content of the RichTextBox. Store the last character printed.
  checkPrint = Me.Print(checkPrint, Me.TextLength, e)
  If checkPrint < Me.TextLength Then ' Look for more pages
    e.HasMorePages = True
  Else
    e.HasMorePages = False
  End If
End Sub

See Below:

RichTextBoxPrint Event Handlers

Step 8

The RichTextBoxPrint Class is now Completed, to use it in the application click on Build, then "Build RichTextEditor":

Build RichTextEditor

You may be asked to Save your Project, when you do and the Build has completed. Select the RichTextBoxPrint Component that appears in the Toolbox under RichTextEditor Components:

RichTextBoxPrint Component

Step 9

Draw the RichTextBoxPrint Component on the Form, see below:

frmMain with RichTextBoxPrint

Step 10

Then goto the Properties box and change the Name to rtbEditor, Dock to Fill and Scrollbars to Vertical, see Below:

RichTextBoxPrint Properties

Step 11

Then from the Menus & Toolbars tab on the Toolbox select the MenuStrip Control, see Below:

MenuStrip Component

Step 12

Either double-click on the MenuStrip Control entry in the Menu & Toolbars tab on the Toolbox or keep the MenuStrip Component Clicked and then move it over the Form then let go. Change the Name of the MenuStrip in the properties to mnuRichText. The Form will then look as below:

frmMain with MenuStrip

Step 13

Click or select where the MenuStrip says "Type Here", an editable Textbox will appear type in "File" without the quotes in this Box, then in the Box below that type in "New", below that "Open...", then "Save...", then "-" which is minus or the hyphen key which will appear as a Seperator, then "Print...", "Print Preview..." and below that "Page Setup", then "-" again for another Seperator, and then finally "Exit". The MenuStrip should look as below:

mnuRichText with SubMenus

Step 14

Click or select where the MenuStrip says "Type Here" next to "File", and in this type in "Edit" without the quotes in this Box, then in the Box below that type "Cut", then below that "Copy", then "Paste" and "Delete", type in "-" which is minus or the hyphen key for a Seperator, then below that "Select All" and finally "Time/Date". The MenuStrip should look as below:

mnuRichText with Edit Sub Menu Items

Step 15

Click on or select the MenuStrip again, on this next to the Edit menu will be another "Type Here" option this this box type "Format" without the quotes, then in the "Type Here" box under that type "Font...", then below that "Colour...", then "Highlight", then type "-" which is minus or the hyphen key for a Seperator, then "Align Left", below that "Align Centre", then "Align Right", then "-" again for a Seperator, then below that type "Bold", then "Italics", then "Underline", then "-" for another Seperator and finally "Bullets", see below:

mnuRichText with Format Sub Menu Items

Step 16

Click on "File" on the MenuStrip to show the MenuStrip then Double Click on the Menu Item Labeled "New" (NewToolStripMenuItem) and type the following in the NewToolStripMenuItem_Click() Sub:

Dim Response As MsgBoxResult
Response = MsgBox("Are you sure you want to start a New Document?", _
                  MsgBoxStyle.Question + MsgBoxStyle.YesNo, _
                  "Rich Text Editor")
If Response = MsgBoxResult.Yes Then
    rtbEditor.Clear()
    Me.Text = "Rich Text Text Editor - Untitled"
End If

See Below:

File Menu New Menu Item Click Event

Step 17

Click on the [Design] Tab to view the form again, then Click on "File" on the MenuStrip to show the MenuStrip then Double Click on the Menu Item Labeled "Open..." (OpenToolStripMenuItem) and type the following in the OpenToolStripMenuItem_Click() Sub:

Dim Open As New OpenFileDialog()
Open.Filter = "Rich Text Document (*.rtf)|*.rtf|All files (*.*)|*.*"
Open.CheckFileExists = True
If Open.ShowDialog(Me) = Windows.Forms.DialogResult.OK Then
    Try
        rtbEditor.LoadFile(Open.FileName)
        Me.Text = "Rich Text Editor - " & Open.FileName
    Catch ex As Exception
        ' Do nothing on Exception
    End Try
End If

See Below:

File Menu Open Menu Item Click Event

Step 18

Click on the [Design] Tab to view the form again, then Click on "File" on the MenuStrip to show the MenuStrip then Double Click on the Menu Item Labeled "Save..." (SaveToolStripMenuItem) and type the following in the SaveToolStripMenuItem_Click() Sub:

Dim Save As New SaveFileDialog()
Save.Filter = "Rich Text Document (*.rtf)|*.rtf|All files (*.*)|*.*"
Save.CheckPathExists = True
If Save.ShowDialog(Me) = Windows.Forms.DialogResult.OK Then
    Try
        rtbEditor.SaveFile(Save.FileName)
        Me.Text = "Rich Text Editor - " & Save.FileName
    Catch ex As Exception
        ' Do nothing on Exception
    End Try
End If

See Below:

File Menu Save Menu Item Click Event

Step 19

Click on the [Design] Tab to view the form again, then Click on "File" on the MenuStrip to show the MenuStrip then Double Click on the Menu Item Labeled "Print..." (PrintToolStripMenuItem) and type the following in the PrintToolStripMenuItem_Click() Sub:

Dim PrintDialog As New PrintDialog()
PrintDialog.Document = rtbEditor.PrintDocument
If PrintDialog.ShowDialog(Me) = DialogResult.OK Then
    Try
        rtbEditor.PrintDocument.Print() ' Print Document
    Catch ex As Exception
        ' Do nothing on Exception
    End Try
End If

See Below:

File Menu Print Menu Item Click Event

Step 20

Click on the [Design] Tab to view the form again, then Click on "File" on the MenuStrip to show the MenuStrip then Double Click on the Menu Item Labeled "Print Preview..." (PrintPreviewToolStripMenuItem) and type the following in the PrintPreviewToolStripMenuItem_Click() Sub:

Dim PrintPreview As New PrintPreviewDialog()
PrintPreview.Document = rtbEditor.PrintDocument
PrintPreview.ShowDialog(Me)

See Below:

File Menu Print Preview Menu Item Click Event

Step 21

Click on the [Design] Tab to view the form again, then Click on "File" on the MenuStrip to show the MenuStrip then Double Click on the Menu Item Labeled "Page Setup..." (PageSetupToolStripMenuItem) and type the following in the PageSetupToolStripMenuItem_Click() Sub:

Dim PageSetup As New PageSetupDialog
PageSetup.Document = rtbEditor.PrintDocument
If PageSetup.ShowDialog(Me) = DialogResult.OK Then
    Try
        rtbEditor.PrintDocument.PrinterSettings = _
        PageSetup.PrinterSettings ' Set Page Settings
    Catch ex As Exception
        ' Do nothing on Exception
    End Try
End If

See Below:

File Menu Page Setup Menu Item Click Event

Step 22

Click on the [Design] Tab to view the form again, then Click on "File" on the MenuStrip to show the MenuStrip then Double Click on the Menu Item Labeled "Exit" (ExitToolStripMenuItem) and type the following in the ExitToolStripMenuItem_Click() Sub

        Dim Response As MsgBoxResult
        Response = MsgBox("Are you sure you want to Exit Rich Text Editor?", _
                          MsgBoxStyle.Question + MsgBoxStyle.YesNo, _
                          "Rich Text Editor")
        If Response = MsgBoxResult.Yes Then
            End
        End If

See Below:

File Menu Exit Menu Item Click Event

Step 23

Click on the [Design] Tab to view the form again, then Click on "Edit" on the MenuStrip, then Double Click on the Menu Item Labeled "Cut" (CutToolStripMenuItem) and type the following in the CutToolStripMenuItem_Click() Sub:

rtbEditor.Cut()

Click on [Design] tab or double click on the frmMain entry in Solution Explorer again, click "Edit", then Double Click on the Menu Item Labeled "Copy" (CopyToolStripMenuItem) and type the following in the CopyToolStripMenuItem_Click() Sub:

rtbEditor.Copy()

Click on [Design] tab or double click on the frmMain entry in Solution Explorer again, click "Edit", then Double Click on the Menu Item Labeled "Paste" (PasteToolStripMenuItem) and type the following in the PasteToolStripMenuItem_Click() Sub:

rtbEditor.Paste()

Click on [Design] tab or double click on the frmMain entry in Solution Explorer again, click "Edit", then Double Click on the Menu Item Labeled "Delete" (DeleteToolStripMenuItem) and type the following in the DeleteToolStripMenuItem_Click() Sub:

rtbEditor.SelectedText = ""

See Below:

Edit Menu Cut, Copy, Paste and Delete Events

Step 24

Click on the [Design] Tab to view the form again, then Click on "Edit" on the MenuStrip, then Double Click on the Menu Item Labeled "Select All" (SelectAllToolStripMenuItem) and type the following in the SelectAllToolStripMenuItem_Click() Sub:

rtbEditor.SelectAll()

Click on [Design] tab or double click on the frmMain entry in Solution Explorer again, click "Edit", then Double Click on the Menu Item Labeled "Time/Date" (TimeDateToolStripMenuItem) and type the following in the TimeDateToolStripMenuItem_Click() Sub:

rtbEditor.SelectedText = Format(Now, "HH:mm dd/MM/yyyy")

See Below:

Edit Menu Select All and Time/Date Events

Step 25

Click on the [Design] Tab to view the form again, then Click on "Format" on the MenuStrip, then Double Click on the Menu Item Labeled "Font..." (FontToolStripMenuItem) and type the following in the FontToolStripMenuItem_Click() Sub

Dim Font As New FontDialog()
Font.Font = rtbEditor.SelectionFont
If Font.ShowDialog(Me) = DialogResult.OK Then
    Try
        rtbEditor.SelectionFont = Font.Font
    Catch ex As Exception
        ' Do nothing on Exception
    End Try
End If

See Below:

Format Menu Font Menu Item Click Event

Step 26

Click on the [Design] Tab to view the form again, then Click on "Format" on the MenuStrip, then Double Click on the Menu Item Labeled "Colour..." (ColourToolStripMenuItem) and type the following in the ColourToolStripMenuItem_Click() Sub

Dim Colour As New ColorDialog()
Colour.Color = rtbEditor.SelectionColor
If Colour.ShowDialog(Me) = DialogResult.OK Then
    Try
        rtbEditor.SelectionColor = Colour.Color
    Catch ex As Exception
        ' Do nothing on Exception
    End Try
End If

See Below:

Format Menu Colour Menu Item Click Event

Step 27

Click on the [Design] Tab to view the form again, then Click on "Format" on the MenuStrip, then Double Click on the Menu Item Labeled "Highlight..." (HighlightToolStripMenuItem) and type the following in the HighlightToolStripMenuItem_Click() Sub

Dim Colour As New ColorDialog()
Colour.Color = rtbEditor.SelectionBackColor
If Colour.ShowDialog(Me) = DialogResult.OK Then
    Try
        rtbEditor.SelectionBackColor = Colour.Color
    Catch ex As Exception
        ' Do nothing on Exception
    End Try
End If

See Below:

Format Menu Highlight Menu Item Click Event

Step 28

Click on the [Design] Tab to view the form again, then Click on "Format" on the MenuStrip, then Double Click on the Menu Item Labeled "Align Left" (AlignLeftToolStripMenuItem) and type the following in the AlignLeftToolStripMenuItem_Click() Sub:

rtbEditor.SelectionAlignment = HorizontalAlignment.Left
AlignLeftToolStripMenuItem.Checked = True
AlignCentreToolStripMenuItem.Checked = False
AlignRightToolStripMenuItem.Checked = False

Click on [Design] tab or double click on the frmMain entry in Solution Explorer again, click "Format", then Double Click on the Menu Item Labeled "Align Centre" (AlignCentreToolStripMenuItem) and type the following in the AlignCentreToolStripMenuItem_Click() Sub:

rtbEditor.SelectionAlignment = HorizontalAlignment.Center
AlignLeftToolStripMenuItem.Checked = False
AlignCentreToolStripMenuItem.Checked = True
AlignRightToolStripMenuItem.Checked = False

Click on [Design] tab or double click on the frmMain entry in Solution Explorer again, click "Format", then Double Click on the Menu Item Labeled "Align Right" (AlignRightToolStripMenuItem) and type the following in the AlignRightToolStripMenuItem_Click() Sub:

rtbEditor.SelectionAlignment = HorizontalAlignment.Right
AlignLeftToolStripMenuItem.Checked = False
AlignCentreToolStripMenuItem.Checked = False
AlignRightToolStripMenuItem.Checked = True

See Below:

Format Menu Align Left, Align Centre and Align Right Events

Step 29

Click on the [Design] Tab to view the form again, then Click on "Format" on the MenuStrip, then Double Click on the Menu Item Labeled "Bold" (BoldToolStripMenuItem) and type the following in the BoldToolStripMenuItem_Click() Sub:

If rtbEditor.SelectionFont.Bold Then
  rtbEditor.SelectionFont = New Font(rtbEditor.SelectionFont, _
                                     rtbEditor.SelectionFont.Style And Not FontStyle.Bold)
Else
  rtbEditor.SelectionFont = New Font(rtbEditor.SelectionFont, _
                                     rtbEditor.SelectionFont.Style Or FontStyle.Bold)
End If
BoldToolStripMenuItem.Checked = rtbEditor.SelectionFont.Bold

Click on [Design] tab or double click on the frmMain entry in Solution Explorer again, click "Format", then Double Click on the Menu Item Labeled "Italics" (ItalicsToolStripMenuItem) and type the following in the ItalicsToolStripMenuItem_Click() Sub:

If rtbEditor.SelectionFont.Italic Then
  rtbEditor.SelectionFont = New Font(rtbEditor.SelectionFont, _
                                     rtbEditor.SelectionFont.Style And Not FontStyle.Italic)
Else
  rtbEditor.SelectionFont = New Font(rtbEditor.SelectionFont, _
                                     rtbEditor.SelectionFont.Style Or FontStyle.Italic)
End If
ItalicsToolStripMenuItem.Checked = rtbEditor.SelectionFont.Italic

Click on [Design] tab or double click on the frmMain entry in Solution Explorer again, click "Format", then Double Click on the Menu Item Labeled "Underline" (UnderlineToolStripMenuItem) and type the following in the UnderlineToolStripMenuItem_Click() Sub:

If rtbEditor.SelectionFont.Underline Then
  rtbEditor.SelectionFont = New Font(rtbEditor.SelectionFont, _
                                     rtbEditor.SelectionFont.Style And Not FontStyle.Underline)
Else
  rtbEditor.SelectionFont = New Font(rtbEditor.SelectionFont, _
                                     rtbEditor.SelectionFont.Style Or FontStyle.Underline)
End If
UnderlineToolStripMenuItem.Checked = rtbEditor.SelectionFont.Underline

See Below:

Format Menu Bold, Italics and Underline Events

Step 30

Click on the [Design] Tab to view the form again, then Click on "Format" on the MenuStrip, then Double Click on the Menu Item Labeled "Bullets" (BulletsToolStripMenuItem) and type the following in the BulletsToolStripMenuItem_Click() Sub

rtbEditor.SelectionBullet = Not rtbEditor.SelectionBullet
BulletsToolStripMenuItem.Checked = rtbEditor.SelectionBullet

See Below:

Format Menu Bullets Menu Item Click Event

Step 31

Click on the [Design] Tab to view the form again, then Double Click on the Form (frmMain) and type the following in the frmMain_Load() Sub

AlignLeftToolStripMenuItem.Checked = True
Me.Text = "Rich Text Editor - Untitled"

See Below:

frmMain Load Event

Step 30

While Still in the Code View, if not double click on the Form pr the Window Area of the Form. There should be two Drop-down boxes one labeled (frmMain Events) or (General) and the other is Load or (Declarations). Click on the drop-down box with "(frmMain Events)" in it and select "rtbEditor", then from the other list, select the "SelectionChanged" event from the list of events for rtbEditor, and type in rtbEditor_SelectionChanged() Sub

AlignLeftToolStripMenuItem.Checked = False
AlignCentreToolStripMenuItem.Checked = False
AlignRightToolStripMenuItem.Checked = False
Select Case rtbEditor.SelectionAlignment
  Case HorizontalAlignment.Left
    AlignLeftToolStripMenuItem.Checked = True
  Case HorizontalAlignment.Center
    AlignCentreToolStripMenuItem.Checked = True
  Case HorizontalAlignment.Right
    AlignRightToolStripMenuItem.Checked = True
End Select
BoldToolStripMenuItem.Checked = rtbEditor.SelectionFont.Bold
ItalicsToolStripMenuItem.Checked = rtbEditor.SelectionFont.Italic
UnderlineToolStripMenuItem.Checked = rtbEditor.SelectionFont.Underline
BulletsToolStripMenuItem.Checked = rtbEditor.SelectionBullet

See Below:

rtbEditor SelectionChanged Event

Step 31

Steps 31-34 are optional and just add Keyboard Shortcuts to the MenuItems, you don't have to do these if you don't want to!
Click on the [Design] Tab to view the form again, click on "New" on the MenuStrip then in the Properties box look for the "ShortcutKeys" option and click on the Drop Down arrow where "None" appears. Check the "Ctrl" Checkbox in "Modifiers" and then in the "Key" dropdown list select "N", see below:

File Menu New Menu Item Shortcut Key

Step 32

Set the rest of the "File" MenuItem "ShortcutKeys" Properties except the "Exit" Menu Item, "Open" should be set to "Ctrl+O", "Save" to "Ctrl+S" and "Print" to "Ctrl+P", the File Menu should appear as below:

File Menu with Shortcut Keys

Step 33

Click on or select the "Edit" Menu and set the "ShortcutKeys" Properties, "Cut" should be set to "Ctrl+X", "Copy" to "Ctrl+C", "Paste" to "Ctrl+V", "Delete" should be just "Del" in the Keys drop-down list, "Select All" should be "Ctrl+A", "Time/Date" should be just "F5" from the Keys drop-down list. The Edit Menu should appear as below:

Edit Menu with Shortcut Keys

Step 34

Click on or select the "Format" Menu, select "Align Left" and in the "ShortcutKeys" property type "Ctrl+L", select "Align Centre" and type "Ctrl+E" in the "ShortcutKeys" property, "Align Right" should be set to "Ctrl+R". "Bold" to "Ctrl+B", "Italics" to "Ctrl+I" and "Underline" set to "Ctrl+U" The Format Menu should appear as below:

Format Menu with Shortcut Keys

Step 35

Save the Project as you have now finished the application, then click on Start:

Start

When you do the following will appear:

Rich Text Editor Running

Step 36

You can create your own Rich Text Documents or Open an existing one to edit, see below:

Rich Text Editor

Step 37

Click File then Exit or click on the Close button Close on the top right of the Rich Text Editor to end the application.

This program uses an extended verison of the standard Rich Text Box to enable Printing, you can use the normal Rich Text Box instead and remove the Printing functions if you wish. This application has all the main features of a Rich Text Editor, see if you can add more!