Click here to Skip to main content
Click here to Skip to main content

Richer RichTextBox (Part 1)

, 27 Oct 2005
Rate this:
Please Sign up or sign in to vote.
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.

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).

    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

About the Author

Nikola Stepan
Software Developer
Croatia Croatia
No Biography provided

Comments and Discussions

 
QuestionSave the text as plain text Pinmembertriplebit3-Oct-13 19:00 
QuestionIncrease / Decrease Fontsize by 1? Pinmembertclaus22-Apr-08 22:09 
GeneralFont PinmemberShin-Ra29-Mar-07 18:01 
GeneralColor Pinmembersathishtl00718-Nov-06 20:28 
GeneralColor Pinmembersathishtl00718-Nov-06 20:09 
GeneralGetFullLineTex PinmemberDUMITRU Guraliuc18-May-06 23:53 
GeneralChange Font Pinmemberistation1-Nov-05 16:09 
GeneralRe: Change Font PinmemberNikola Stepan2-Nov-05 10:50 
GeneralRe: Change Font Pinmemberistation2-Nov-05 14:05 
GeneralVery Nice! PinmemberOpasnia31-Oct-05 23:54 
Question2 methods for each property? PinmemberTommy Carlier24-Oct-05 22:36 
AnswerRe: 2 methods for each property? Pinmemberigor toporet1-Nov-05 3:53 
Question.. and Part 2 ? Pinmembergxdata24-Oct-05 21:07 
NewsBasic bug Pinmemberleppie24-Oct-05 11:34 
GeneralRe: Basic bug PinmemberNikola Stepan24-Oct-05 19:53 

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

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

| Advertise | Privacy | Mobile
Web03 | 2.8.140721.1 | Last Updated 27 Oct 2005
Article Copyright 2005 by Nikola Stepan
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid