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

Richer RichTextBox (Part 2)

Rate me:
Please Sign up or sign in to vote.
4.11/5 (9 votes)
13 Jan 2006 99K   3.4K   75   6
An article on extending the RichTextBox class in C#.

Sample Image

Introduction

In the first part, we extended the RichTextBox class with methods that change the FontStyle of a selection without losing the styles that are currently present. Unfortunately, there are a few more features missing from the RichTextBox control that could potentially be useful in word-processor-like applications. These kinds of applications commonly use a status bar to display information about the current cursor position. In this part, we will enrich the RichTextBox control with functionality that can be used for that purpose.

Usage

When nothing is selected, we want to display line number, column number and cursor position. When some portion of text is selected, the status bar should display the start, end and length of the selection. Also, from the client perspective, those features should be self-documentary and easy to use.

C#
this.rtb.CursorPositionChanged += 
    new System.EventHandler(this.rtb_CursorPositionChanged);
this.rtb.SelectionChanged += 
    new System.EventHandler(this.rtb_SelectionChanged);
.
.
.
private void rtb_CursorPositionChanged(object sender, System.EventArgs e)
{
    int line = rtb.CurrentLine;
    int col = rtb.CurrentColumn;
    int pos = rtb.CurrentPosition;
    
    statusBar.Text = "Line " + line + ", Col " + col + 
                     ", Position " + pos;
}

private void rtb_SelectionChanged(object sender, System.EventArgs e)
{
    int start = rtb.SelectionStart;
    int end = rtb.SelectionEnd;
    int length = rtb.SelectionLength;
    
    statusBar.Text = "Start " + start + ", End " + end + 
                     ", Length " + length;
}

To achieve such behavior, we need to extend the RichTextBox class in the following manner:

C#
using System;
using System.Drawing;
using System.Windows.Forms;

namespace Nik.UserControls
{
    public class RicherTextBox2 : System.Windows.Forms.RichTextBox
    {
        public event EventHandler CursorPositionChanged;
        
        protected virtual void OnCursorPositionChanged( EventArgs e )
        {
            if ( CursorPositionChanged != null )
                CursorPositionChanged( this, e );
        }

        protected override void OnSelectionChanged( EventArgs e )
        {
            if ( SelectionLength == 0 )
                OnCursorPositionChanged( e );
            else
                base.OnSelectionChanged( e );
        }
            
        public int CurrentColumn
        {
            get { return CursorPosition.Column( this, SelectionStart ); }
        }

        public int CurrentLine
        {
            get { return CursorPosition.Line( this, SelectionStart ); }
        }

        public int CurrentPosition
        {
            get { return this.SelectionStart; }
        }

        public int SelectionEnd
        {
            get { return SelectionStart + SelectionLength; }
        }
    }
    
    internal class CursorPosition
    {
        [System.Runtime.InteropServices.DllImport("user32")] 
        public static extern int GetCaretPos(ref Point lpPoint);

        private static int GetCorrection(RichTextBox e, int index)
        {
            Point pt1 = Point.Empty;
            GetCaretPos(ref pt1);
            Point pt2 = e.GetPositionFromCharIndex(index);

            if ( pt1 != pt2 )
                return 1;
            else
                return 0;
        }

        public static int Line( RichTextBox e, int index )
        {
             int correction = GetCorrection( e, index );
             return e.GetLineFromCharIndex( index ) - correction + 1;
        }

        public static int Column( RichTextBox e, int index1 )
        {
             int correction = GetCorrection( e, index1 );
             Point p = e.GetPositionFromCharIndex( index1 - correction );

             if ( p.X == 1 )
                 return 1;

             p.X = 0;
             int index2 = e.GetCharIndexFromPosition( p );

             int col = index1 - index2 + 1;

             return col;
         }
    }
}

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

 
GeneralSet Cursor Position Pin
Sallac7-Mar-08 0:23
Sallac7-Mar-08 0:23 
GeneralFinding Text Position Pin
mark_e_mark30-Mar-06 4:49
mark_e_mark30-Mar-06 4:49 
Hi Nikola,

Great Article!

I was wondering if you have know of a way that I can extract the text from a RTB and find the position each char is in the display?

I know its a wierd thing to do but I really need to do it...

Regards

Mark Smile | :)
GeneralProblem with column position Pin
gijsvennix2-Jan-06 1:29
gijsvennix2-Jan-06 1:29 
GeneralRe: Problem with column position Pin
Nikola Stepan13-Jan-06 3:46
Nikola Stepan13-Jan-06 3:46 
GeneralRe: Problem with column position Pin
Ribeaucoup Thomas13-Dec-06 22:05
Ribeaucoup Thomas13-Dec-06 22:05 
GeneralRe: Problem with column position Pin
mahone20-Jul-09 5:32
mahone20-Jul-09 5:32 

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.