Click here to Skip to main content
15,880,967 members
Articles / Programming Languages / C#
Article

Richer RichTextBox (Part 1)

Rate me:
Please Sign up or sign in to vote.
3.59/5 (7 votes)
27 Oct 20052 min read 100.1K   1.8K   40   15
An article on extending the RichTextBox class in C#.

Sample Image

Introduction

If you ever tried to write a word processor in C#, you probably encountered some missing features in the RichTextBox class. One of them is lack of methods that can change the FontStyle of a selection without losing the styles that are currently present. There is workaround for this problem described in the WinForms FAQ.

"If you visit the selection a character at a time, you can get the current FontStyle and modify it directly to add or remove a style like Bold or Italic. Doing it a character at a time will avoid losing the other styles that are set. The problem with doing it a whole selection at a time is that the FontStyle of the entire selection is the common styles set among all the characters in the selection. So, if one char is bold and one is not, then bold is not set when you retrieve the font style for the entire selection. Doing things a character at a time avoids this problem and allows things to work OK."

Although working, this solution is not without flaws. Visiting one character at a time causes flickering and it is inefficient with large selections. Fortunately, the .NET RichTextBox control is based on the Win32 RichEdit control that has wanted functionality. To reach it, we will extend the RichTextBox and add the necessary wrappers that send the messages to the underlying RichEdit control.

C#
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace Nik.UserControls
{
    public class RicherTextBox1 : System.Windows.Forms.RichTextBox
    {
        private const int EM_SETCHARFORMAT = 1092;
        
        private const int CFM_BOLD = 1;
        private const int CFM_ITALIC = 2;
        private const int CFM_UNDERLINE = 4;
        
        private const int SCF_SELECTION = 1;

        [StructLayout( LayoutKind.Sequential )]
        private struct CHARFORMAT
        {
            public int cbSize;
            public uint dwMask;
            public uint dwEffects;
            public int yHeight;
            public int yOffset;
            public int crTextColor;
            public byte bCharSet;
            public byte bPitchAndFamily;
            [MarshalAs( UnmanagedType.ByValArray, SizeConst = 32 )]
            public char[] szFaceName;
            
            // CHARFORMAT2 from here onwards.
            public short wWeight;
            public short sSpacing;
            public int crBackColor;
            public int LCID;
            public uint dwReserved;
            public short sStyle;
            public short wKerning;
            public byte bUnderlineType;
            public byte bAnimation;
            public byte bRevAuthor;
        }

        [DllImport( "user32", CharSet = CharSet.Auto )]
        private static extern int SendMessage( HandleRef hWnd, 
                int msg, int wParam, ref CHARFORMAT lp );

        private void SetCharFormatMessage( ref CHARFORMAT fmt )
        {
            SendMessage(new HandleRef(this, Handle), 
                  EM_SETCHARFORMAT, SCF_SELECTION, ref fmt);
        }

        public void SetSelectionBoldOn()
        {
            ApplyStyle( CFM_BOLD, true );
        }

        public void SetSelectionBoldOff()
        {
            ApplyStyle( CFM_BOLD, false );
        }

        public void SetSelectionItalicOn()
        {
            ApplyStyle( CFM_ITALIC, true );
        }

        public void SetSelectionItalicOff()
        {
            ApplyStyle( CFM_ITALIC, false );
        }

        public void SetSelectionUnderlineOn()
        {
            ApplyStyle( CFM_UNDERLINE, true );
        }

        public void SetSelectionUnderlineOff()
        {
            ApplyStyle( CFM_UNDERLINE, false );
        }
            
         private void ApplyStyle( uint style, bool on )
         {

             CHARFORMAT fmt = new CHARFORMAT();
             fmt.cbSize = Marshal.SizeOf( fmt );
             fmt.dwMask = style;

             if ( on )
                 fmt.dwEffects = style;
             SetCharFormatMessage( ref fmt );
         }
    }
}

Usage

Our new control retains all of the functionality of the standard RichTextbox control but also incorporates custom functionality. We can now use our control instead of the RichTextBox and invoke new methods like any other method in the RichTextBox control (see demo 2).

C#
private void boldOn_Click(object sender, System.EventArgs e)
{
    rtb.SetSelectionBoldOn();
}

private void italicOn_Click(object sender, System.EventArgs e)
{
    rtb.SetSelectionItalicOn();
}

private void underlineOn_Click(object sender, System.EventArgs e)
{
    rtb.SetSelectionUnderlineOn();
}

private void boldOff_Click(object sender, System.EventArgs e)
{
    rtb.SetSelectionBoldOff();
}

private void italicOff_Click(object sender, System.EventArgs e)
{
    rtb.SetSelectionItalicOff();
}

private void underlineOff_Click(object sender, System.EventArgs e)
{
    rtb.SetSelectionUnderlineOff();
}

Resources

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer
Croatia Croatia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionSave the text as plain text Pin
triplebit3-Oct-13 19:00
triplebit3-Oct-13 19:00 
I need to save the text as plain text.
Is it possible?
If yes, can someone demonstrate how to do it?
Thanks in advance.
Kishon
QuestionIncrease / Decrease Fontsize by 1? Pin
tclaus22-Apr-08 22:09
tclaus22-Apr-08 22:09 
GeneralFont Pin
Shin-Ra29-Mar-07 18:01
Shin-Ra29-Mar-07 18:01 
GeneralColor Pin
sathishtl00718-Nov-06 20:28
sathishtl00718-Nov-06 20:28 
GeneralColor Pin
sathishtl00718-Nov-06 20:09
sathishtl00718-Nov-06 20:09 
GeneralGetFullLineTex Pin
DUMITRU Guraliuc18-May-06 23:53
DUMITRU Guraliuc18-May-06 23:53 
GeneralChange Font Pin
istation1-Nov-05 16:09
istation1-Nov-05 16:09 
GeneralRe: Change Font Pin
Nikola Stepan2-Nov-05 10:50
Nikola Stepan2-Nov-05 10:50 
GeneralRe: Change Font Pin
istation2-Nov-05 14:05
istation2-Nov-05 14:05 
GeneralVery Nice! Pin
Opasnia31-Oct-05 23:54
Opasnia31-Oct-05 23:54 
Question2 methods for each property? Pin
Tommy Carlier24-Oct-05 22:36
Tommy Carlier24-Oct-05 22:36 
AnswerRe: 2 methods for each property? Pin
Igor Toporet1-Nov-05 3:53
Igor Toporet1-Nov-05 3:53 
Question.. and Part 2 ? Pin
gxdata24-Oct-05 21:07
gxdata24-Oct-05 21:07 
NewsBasic bug Pin
leppie24-Oct-05 11:34
leppie24-Oct-05 11:34 
GeneralRe: Basic bug Pin
Nikola Stepan24-Oct-05 19:53
Nikola Stepan24-Oct-05 19:53 

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.