Richtextbox numéroté (numéros de lignes)

Description

Ce code est un exemple de ce que j'utilise pour un éditeur de fichiers que j'ai développé. Lorsque le format est reconnu, il est affiché en colonnes dans une grille (contrôle "SourceGrid"), dans les autres cas, le contenu du fichier est simplement chargé sous forme de text ASCI dans un RichTextBox.

Afin de mieux ressembler à un éditeur de texte universel genre PSPad ou UltraEdit, mais surtout permettre de retrouver des informations par exemple selon les détails d'un fichier log, j'ai voulu afficher les numéros de lignes à gauche du texte.

Voici ma solution.

Note: étant donné que je développe en anglais au boulot, ici j'ai procédé de la même manière: les contrôles, variables et commentaires sont en anglais.
Mais je ne crois pas que ce soit très compliqué et vous pouvez toujours me poser des questions via les commentaires ci-dessous.
(Merci de ne pas me demander des développements personnalisés par MP !!)

Source / Exemple :


/*



using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace NumRichTextBox
{
    public partial class TextEditor : Form
    {
        public TextEditor()
        {
            InitializeComponent();

            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            SetStyle(ControlStyles.DoubleBuffer, true);
            SetStyle(ControlStyles.ResizeRedraw, true);
        }

        public void OpenFile(string filename)
        {
            try
            {
                // Load specified file in the RichTextBox
                this.richTextBox.LoadFile(filename, RichTextBoxStreamType.PlainText);
            }
            catch (Exception)
            {
                // Display error message
                MessageBox.Show("Unable to open specified file!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                // Close window
                this.Close(); 
            }

        }

        private void DrawLines(Graphics g, int firstLine)
        {
            // Number of text lines
            int linesCount = richTextBox.Lines.Length;

            // Last visible line (used to determine numbers panel width)
            int lastChar = this.richTextBox.GetCharIndexFromPosition(new Point(this.richTextBox.ClientRectangle.Width, this.richTextBox.ClientRectangle.Height));
            int lastLine = this.richTextBox.GetLineFromCharIndex(lastChar);

            // Line numbers layout (position, width)
            int rightMargin = 2, leftMargin = 5, topMargin = 2, bottomMargin = 15, verticalMargin = 2;
            SizeF maxTextSize = g.MeasureString(new string((char)48, lastLine.ToString().Length), this.richTextBox.Font);
            this.panelNum.Width = (int)maxTextSize.Width + leftMargin + rightMargin;

            // Clear existing numbers
            g.Clear(this.panelNum.BackColor);

            // First line name
            int lineNumber = firstLine + 1;

            // Y position for first line number
            int firstLineY = this.richTextBox.GetPositionFromCharIndex(this.richTextBox.GetFirstCharIndexFromLine(firstLine)).Y;
            int lineY = topMargin + firstLineY;

            // Write all visible line numbers
            while (true)
            {
                // Draw line number string
                string lineNumberLabel = lineNumber.ToString().PadLeft(lastLine.ToString().Length);
                g.DrawString(lineNumberLabel, this.richTextBox.Font, Brushes.Black, leftMargin, lineY);

                // Next line
                lineNumber += 1;
                lineY += Font.Height + verticalMargin;

                // End of numeration if and of text content or end of RichTextBox height
                if (lineY > ClientRectangle.Height - bottomMargin || lineNumber > linesCount)
                    break;
            }
        }

        private void panelNum_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            // Update the line numbers
            int firstChar = this.richTextBox.GetCharIndexFromPosition(new Point(0, 0));
            int firstLine = this.richTextBox.GetLineFromCharIndex(firstChar);

            DrawLines(e.Graphics, firstLine);
        }

        private void richTextBox_SelectionChanged(object sender, System.EventArgs e)
        {
            this.panelNum.Invalidate(); // Request repaint => line numbers update
        }

        private void richTextBox_VScroll(object sender, System.EventArgs e)
        {
            this.panelNum.Invalidate(); // Request repaint => line numbers update
        }

        private void TextEditor_Load(object sender, EventArgs e)
        {
            // Required properties
            this.richTextBox.ScrollBars = RichTextBoxScrollBars.Both;
            this.richTextBox.WordWrap = false;

            // Required events
            this.richTextBox.SelectionChanged += new System.EventHandler(this.richTextBox_SelectionChanged);
            this.richTextBox.VScroll += new System.EventHandler(this.richTextBox_VScroll);
            this.panelNum.Paint += new PaintEventHandler(this.panelNum_Paint);
        }

    }
}

Conclusion :


Dans mon cas une feuille "child" MDI est uniquement constituée du texte (RichTextBox) et des numéros de lignes (Panel).
Mais on peut bien sûr modifier ou ajouter des éléments.
Une solution "de luxe" pourrait aussi être de créer un UserControl.

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.