Feedback

C# - Syntax-Highlighting

Veröffentlicht von am 10/28/2011
(2 Bewertungen)
So nun will ich auch eine mehr oder weniges kleines Snippet (das 1.) hinzufügen. Ist eine von RichTextBox abgeleitete Klasse die auch eine TextBox zur Verfügung stellt wo vorher definierte Wörter gehilightet wird ähnlich wie beim Syntax Highlighting!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Threading;

namespace Boxes
{
    /// <summary>
    /// Die Klasse stellt eine RichTextBox bereit, in der vordefinierte Wörter eingefärbt werden. 
    /// Wörter die eingefärbt werden sollen, werden durch vordefinierte Trennzeichen separiert, 
    /// geprüft und ggf. gefärbt.
    /// </summary>
    /// <remarks>
    /// Autor: Daniel Lutz 
    /// Copyright: Daniel Lutz
    /// Für private Nutzung kostenlos! Bei gewerblicher Nutzung wird vorhergehende Erleubnis benötigt!
    /// Erstellt: Oktober 2011
    /// </remarks>
    public class HighLightingBox : RichTextBox
    {
        #region Variable
    
        RichTextBox m_thisCopy;
        List<string> m_SelectionWordList;
        List<char>m_SeperatorList=new List<char>();
        char[] m_Seperators;
        Color m_Color;
        int m_CursorPosition;
        bool m_IsSingleWordColoring = false;
        bool m_IsWholeTextColoring = false;
        bool m_IsChangeColoring = false;
        IDataObject m_objClipBoard;
        int ClipBoardValueLenght;

        #endregion

        #region Konstruktor

        /// <summary>
        /// Konstruktor um die benötigten Werte zu initialisieren.
        /// </summary>
        /// <param name="_Seperators">Zu verwendene Trennzeichen</param>
        /// <param name="_Words">Wörter die hervorgehoben werden soll</param>
        /// <param name="_Font">Verwendete Schriftart</param>
        /// <param name="_Color">Farbe der Hervorhebung</param>
        public HighLightingBox(char[] _Seperators, List<string> _Words, Font _Font, Color _Color)
        {
            m_SelectionWordList = _Words;
            m_Color = _Color;
            m_Seperators = _Seperators;
            this.Font = _Font;
            this.TextChanged+=new EventHandler(this_TextChangedEvent);
            this.KeyDown+=new KeyEventHandler(this_KeyDown);
            ListCreate();
        }

        #endregion
        
        #region Methode

        /// <summary>
        /// Erzeugt aus den übergebenden Trennzeichen eine Liste
        /// </summary>
        private void ListCreate()
        {
            foreach (char ch in m_Seperators)
            { 
            m_SeperatorList.Add(ch);
            }
        }

        /// <summary>
        /// Färbt einzelne Wörte in einem definierten Bereich
        /// </summary>
        /// <param name="values">Wertebereich</param>
        private void ColoringWord(int[] values)
        {
            m_IsSingleWordColoring = true;
            int WordLengthCounter = 0;
            this.Select(values[0], values[1] - values[0]);
            foreach (string temp in (this.SelectedText.Split(m_Seperators)))
            {
                this.Select(values[0] + WordLengthCounter, temp.Length);
                if (m_SelectionWordList.Contains(this.SelectedText.Trim()))
                {
                    this.SelectionColor = m_Color;
                    this.SelectionFont = (new Font(this.SelectionFont, FontStyle.Bold));
                }
                else
                {
                    this.SelectionColor = Color.Black;
                    this.SelectionFont = (new Font(this.SelectionFont, FontStyle.Regular));
                }
                WordLengthCounter += temp.Length + 1;
            }
         
            m_IsSingleWordColoring = false;
        }

        /// <summary>
        /// Färbt Text in einem definierten Bereich
        /// </summary>
        /// <param name="position"></param>
        private void ColoringText(int position)
        {
            int[] Borders = GetTextRange();
            m_IsWholeTextColoring = true;
                int merker;
                int merker2;
                for (m_thisCopy.SelectionStart = Borders[0]; m_thisCopy.SelectionStart < Borders[1]; m_thisCopy.SelectionStart++)
                {
                    merker = m_thisCopy.SelectionStart;
                    m_thisCopy.Select(m_thisCopy.SelectionStart, 1);
                    if (!m_SeperatorList.Contains(m_thisCopy.SelectedText[0]))
                    {
                        for (int j = m_thisCopy.SelectionStart; j < Borders[1]; j++)
                        {
                            merker2 = j;
                            m_thisCopy.Select(j, 1);
                            if (j + 1 != Borders[1])
                            {
                                if (m_SeperatorList.Contains(m_thisCopy.SelectedText[0]))
                                {
                                    m_thisCopy.Select(merker, merker2 - merker);

                                    if (m_SelectionWordList.Contains(m_thisCopy.SelectedText.Trim()))
                                    {
                                        m_thisCopy.SelectionColor = m_Color;
                                        m_thisCopy.SelectionFont = (new Font(m_thisCopy.SelectionFont, FontStyle.Bold));
                                    }
                                    else
                                    {
                                        m_thisCopy.SelectionColor = Color.Black;
                                        m_thisCopy.SelectionFont = (new Font(m_thisCopy.SelectionFont, FontStyle.Regular));
                                    }
                                    m_thisCopy.SelectionStart = merker2;
                                    break;
                                }
                            }
                            else
                            {
                                m_thisCopy.Select(merker, merker2+1 - merker);

                                if (m_SelectionWordList.Contains(m_thisCopy.SelectedText.Trim()))
                                {
                                    m_thisCopy.SelectionColor = m_Color;
                                    m_thisCopy.SelectionFont = (new Font(m_thisCopy.SelectionFont, FontStyle.Bold));
                                }
                                else
                                {
                                    m_thisCopy.SelectionColor = Color.Black;
                                    m_thisCopy.SelectionFont = (new Font(m_thisCopy.SelectionFont, FontStyle.Regular));
                                }
                                m_thisCopy.SelectionStart = merker2;
                                break;
                            }
                        }
                    }
                }
                this.Rtf = m_thisCopy.Rtf;
                this.SelectionStart = position;
                this.SelectionLength = 0;
                m_IsWholeTextColoring = false;
                m_thisCopy = null; 
        }

        /// <summary>
        /// Dininiert Wertebereich für das Färben einzelner Worte
        /// </summary>
        /// <returns>Definitionsbereich</returns>
        private int[] GetWordRange()
        {
            int value_1;
            int value_2;

            string[] part_1 = this.Text.Substring(0, this.SelectionStart).Split(m_Seperators);
            string[] part_2 = this.Text.Substring(this.SelectionStart).Split(m_Seperators);

           if(part_1.Length > 1)
           {
               if (part_1[part_1.Length - 1].Length != 0)
               {
                   value_1 = this.SelectionStart - part_1[part_1.Length - 1].Length;
               }
               else
               {
                   value_1 = this.SelectionStart - part_1[part_1.Length - 1].Length - 1 - part_1[part_1.Length - 2].Length;
               }
           }
           else
           {
               if (part_1.Length > 0)
               {
                   value_1 = this.SelectionStart - part_1[0].Length;
               }
               else
               {
                   value_1 = 0;
               }
           }

           if (part_2.Length >= 2)
           {
               if (part_2[0].Length == 0)
               {
                   value_2 = this.SelectionStart + part_2[0].Length + 1 + part_2[1].Length;
               }
               else
               {
                   value_2 = this.SelectionStart + part_2[0].Length;
               }
           }
           else
           {
               if (part_2.Length == 1 )
               {
                   value_2 = this.SelectionStart + part_2[0].Length;
               }
               else
               {
                   value_2 = 0;
               }
           }

            return new int[] { value_1, value_2 };
        }

        /// <summary>
        /// Deiniert Wertebereich für das Färben von Texten
        /// </summary>
        /// <returns>Definitionsbereich</returns>
        private int[] GetTextRange()
        {
            if (m_IsChangeColoring)
            {
                m_IsChangeColoring = false;
                return new int[]{0,m_thisCopy.Text.Length};
            }

            RichTextBox copy = new RichTextBox();
            copy.Text = this.Text;
            copy.SelectionStart = m_thisCopy.SelectionStart-ClipBoardValueLenght;
            int position = copy.SelectionStart + ClipBoardValueLenght;
            int value_1=0;
            int value_2 = 0;

            if (copy.SelectionStart == 0)
            { value_1 = 0; }
            else
            {
                while (copy.SelectionStart > 0)
                {
                    copy.SelectionStart -= 1;
                    m_thisCopy.Select(copy.SelectionStart,1);
                    if(m_SeperatorList.Contains(m_thisCopy.SelectedText[0]))
                    {
                    value_1=copy.SelectionStart+1;
                    break;
                    }
                }
            }

            copy.Text = m_thisCopy.Text;
            copy.SelectionStart = position + 1;

            if (copy.SelectionStart == copy.Text.Length || copy.SelectionStart > copy.Text.Length)
            { 
                value_2 = m_thisCopy.Text.Length; 
            }
            else
            {
                while (copy.SelectionStart < copy.Text.Length)
                {
                    copy.Select(copy.SelectionStart, 1);
                    if (m_SeperatorList.Contains(copy.SelectedText[0]))
                    {
                        value_2 = copy.SelectionStart;
                        break;
                    }
                    copy.SelectionStart += 1;
                    if (copy.SelectionStart == copy.Text.Length)
                    {
                        value_2 = copy.SelectionStart;
                        break;
                    }
                }
            }

            return new int[] { value_1, value_2 };
        }

        /// <summary>
        /// Setzt die Farbe für Hervorhebungen neu
        /// </summary>
        /// <param name="HColor">Neue Farbe</param>
        public void SetColor(Color HColor)
        {
            m_Color = HColor;
            m_thisCopy = new RichTextBox();
            m_thisCopy.Rtf = this.Rtf;
            m_IsChangeColoring = true;
            ColoringText(this.SelectionStart);
        }

        /// <summary>
        /// Verarbeitet Textänderungen in ColorBox
        /// </summary>
        /// <param name="sender">ColorBox Object</param>
        /// <param name="e">Eventargs</param>
        private void this_TextChangedEvent(object sender, EventArgs e)
        {
            if (!m_IsWholeTextColoring)
            {
                if (!m_IsSingleWordColoring)
                {
                    int[] temp = GetWordRange();
                    m_CursorPosition = this.SelectionStart;
                    ColoringWord(temp);
                    this.SelectionStart = m_CursorPosition;
                    this.SelectionLength = 0;
                }
            }
        }

        /// <summary>
        /// Verarbeitet Tastatureingaben und startet ggf. komplette Textüberprüfung
        /// </summary>
        /// <param name="sender">ColorBox Object</param>
        /// <param name="e"></param>
        private void this_KeyDown(object sender, KeyEventArgs e)
        {

            if (e.KeyData == (Keys.Control|Keys.V))
            {
                e.Handled=true;
                m_objClipBoard = Clipboard.GetDataObject();
                try
                {
                    m_thisCopy=new RichTextBox();
                    m_thisCopy.Rtf = this.Rtf;
                    string temp= m_objClipBoard.GetData(DataFormats.Text).ToString();
                    InsertText(temp);
                    ColoringText(m_thisCopy.SelectionStart);
                }
                catch (NullReferenceException)
                {
                    MessageBox.Show(this, "Es befindet sich kein Text in der Zwischenablage!", "Fehlermeldung", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                m_objClipBoard = null;
            }
        }

        /// <summary>
        /// Fügt Text aus der Zwischenablage ein
        /// </summary>
        /// <param name="value">Zwischenablageninhalt</param>
        private void InsertText(string value)
        {
            int position = this.SelectionStart;
            int PreViewLenght = m_thisCopy.Text.Length;
            m_IsWholeTextColoring = true;
            if (this.SelectionLength == 0)
            {
                this.SelectionColor = Color.Black;
                this.Select(this.SelectionStart, 0);
                this.SelectedText=value;
                m_thisCopy.Rtf = this.Rtf;
            }
            else
            {
                this.Select(this.SelectionStart, this.SelectionLength);
                this.SelectedText = this.SelectedText.Remove(0, this.SelectedText.Length);
                this.SelectionColor = Color.Black;
                this.SelectedText = value;
                m_thisCopy.Rtf = this.Rtf;
            }
            if (m_thisCopy.Text.Length != PreViewLenght)
            {
                m_thisCopy.SelectionStart = position + m_thisCopy.Text.Length - PreViewLenght;
                ClipBoardValueLenght = m_thisCopy.Text.Length - PreViewLenght;
            }
            else
            {
                m_thisCopy.SelectionStart = m_thisCopy.Text.Length;
                ClipBoardValueLenght = m_thisCopy.Text.Length;
            }
        }

        #endregion
    }
}

5 Kommentare zum Snippet

Lutze schrieb am 10/28/2011:
Es ist die 1. Version die ich nebenbei bei einem Grundlehrgang f+r C# mir erdacht habe. Ich weiß das nicht alles davon sinnvoll ist aber ich programmiere erst seit 1. Jahr und bringe mir das selber bei! Wegen den Copyright Anmerkungen, die Sind in meiner Standardvorlage definiert!
Fawk_18 schrieb am 11/18/2011:
Ansatz ist super aber in dieser form vielleicht nicht so zu gebrauchen. Ich hätte anstatt einer Wordlist mir alle Assemblies vom Framework (oder vielleicht auch vom GAC) als Assembly-Object geholt und mir von diesen Infos die Namespaces, Interfaces, Klassen ...etc geholt und diese als Wordlist benutzen.

DANN hättest du eine SyntaxTextbox ;-) trotzdem guter ansatz!
hackman schrieb am 11/21/2011:
lol, programmiert seit einem jahr aber als erstes mal ne richtige vorlage mit copyright templates erstellt ...
Krzysztof schrieb am 11/30/2011:
gute Arbeit

using System.ComponentModel;

string[] _KeyWords = new string[] { "function", "if", "new", "string", "while" };
[Browsable(true), Description("KeyWords"), DefaultValue(new string[] {"function", "if", "new"}), Category("Daten")]
public string[] KeyWords
{
get
{
return (_KeyWords);
}
set
{
_KeyWords = value;
}
}


und schaue dir System.Reflection an.

Lutze schrieb am 1/6/2012:
Ich hatte das allgemeiner gehalten, dass man selbst definieren kann welches Word gefärbt wird. Das Ding ist definitiv noch ausbaufähig. Echtes Syntaxhighlighting ist es natürlich nicht! Dafür benötige ich dann schon Reflexion und so weiter, das ist klar. Ich hatte mich einfach mal daran versucht wie so was aussehen könnte. (Wenn mann einen längeren Text einfügt dann dauert es ja ziemlich lange bis man ihn sieht, da er ja komplett durchlaufen werden muss. Dafür hatte ich irgendwie noch keine gute Idee)
 

Logge dich ein, um hier zu kommentieren!