Bonjour, voici une class dérivé de RichTextBox servant d'editeur syntaxique C#
il prend en charge les mot clé , les commentaires //, les commentaire multiligne /**/
ainsi que les string "" ou @"" simple ou multiligne
il utilise TOM OBJECT MODEL pour mettre a jour les couleurs sans gener l'utilisateur
il y a un Thread qui est lancé Sur l'evenement OnTextChanged
Source / Exemple :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using tom;
using System.Runtime.InteropServices;
using System.Threading;
using System.Text.RegularExpressions;
using System.Drawing;
namespace IrcChatClient.SpecificControls
{
public class RichEditorCsharp : RichTextBox
{
private Thread th = null;
public RichEditorCsharp()
{
}
#region WIN32
[DllImport("User32.dll")]
public static extern int SendMessage(IntPtr hWnd, int message, IntPtr wParam, out IntPtr lParam);
private const int EM_GETOLEINTERFACE = WM_USER + 60;
public const int WM_USER = 0x0400;
#endregion
#region TOM OBJECT MODEL
private ITextDocument _myITextDocument = null;
private ITextDocument myITextDocument
{
get
{
if (_myITextDocument == null)
_myITextDocument = Create();
return _myITextDocument;
}
set
{
if (_myITextDocument != null)
Marshal.ReleaseComObject(_myITextDocument);
_myITextDocument = value;
}
}
private ITextDocument Create()
{
IntPtr theRichEditOle = IntPtr.Zero;
if (SendMessage(Handle, EM_GETOLEINTERFACE, IntPtr.Zero, out theRichEditOle) == 0)
{
throw new System.ComponentModel.Win32Exception();
}
try
{
ITextDocument theTextDoc = (ITextDocument)Marshal.GetTypedObjectForIUnknown(theRichEditOle, typeof(ITextDocument));
return theTextDoc;
}
finally
{
Marshal.Release(theRichEditOle);
}
}
private void FreezeDocument(ITextDocument doc)
{
doc.Freeze();
}
private void UnFreezeDocument(ITextDocument doc)
{
doc.Unfreeze();
}
private Boolean setForeColor(int start, int len, System.Drawing.Color backcolor)
{
Boolean ret = false;
ITextRange range = myITextDocument.Range(start, start + len);
FreezeDocument(myITextDocument);
range.Font.ForeColor = System.Drawing.ColorTranslator.ToOle(backcolor);
UnFreezeDocument(myITextDocument);
return ret;
}
#endregion
#region DELEGATE
private delegate Boolean Updatecolor(int start, int len, System.Drawing.Color backcolor);
#endregion
#region KEYWORD C#
private String[] Word = new String[] {
"abstract","as","base","bool","break","byte","case","catch","char","checked","class","const","continue","decimal",
"default","delegate","do","double","else","enum","event","exdouble","exfloat","explicit","extern","false","finally","fixed",
"float","for","foreach","get","goto","if","implicit","in","int","interface","internal","is","lock","long","namespace",
"new","null","object","operator","out","override","private","protected","public","readonly","ref","return","sbyte","sealed",
"set","short","sizeof","static","string","struct","switch","this","throw","true","try","typeof","uint","ulong","unchecked",
"unsafe","ushort","using","virtual","void"
};
/// <summary>
/// gerene un motif de regex
/// </summary>
/// <returns></returns>
private string CompileKeywords()
{
string mKeywords = "";
for (int i = 0; i < Word.Length; i++)
{
string strKeyword = Word[i];
if (i == Word.Length - 1)
mKeywords += "\\b" + Word[i] + "\\b";
else
mKeywords += "\\b" + Word[i] + "\\b|";
}
return mKeywords;
}
#endregion
/// <summary>
/// Mise a jour inter-Thread
/// </summary>
/// <param name="start">debut de mot</param>
/// <param name="len">fin de mot</param>
/// <param name="color">couleur désiré</param>
private void UpdateContent(int start, int len, Color color)
{
if (this.InvokeRequired)
{
this.Invoke(new Updatecolor(setForeColor), new Object[] { start, len, color });
}
else
setForeColor(start, len, color);
}
/// <summary>
/// Color le text
/// </summary>
/// <param name="data">Text de la richtextbox</param>
public void ColorSystaxe(object data)
{
String Text = data as String;
Match regMatch;
UpdateContent(0, Text.Length, Color.Black);
/* color mot clé */
Regex reg = new Regex(CompileKeywords(), RegexOptions.Singleline | RegexOptions.Compiled);
for (regMatch = reg.Match(Text); regMatch.Success; regMatch = regMatch.NextMatch())
{
int nStart = regMatch.Index;
int nLenght = regMatch.Length;
UpdateContent(nStart, nLenght, Color.Blue);
}
/* color string avec ou sans @*/
reg = new Regex("(@\"|\")[^\"]*(?:\\\\.[^\"]*)*\"", RegexOptions.Multiline | RegexOptions.Compiled);
for (regMatch = reg.Match(Text); regMatch.Success; regMatch = regMatch.NextMatch())
{
int nStart = regMatch.Index;
int nLenght = regMatch.Length;
UpdateContent(nStart, nLenght, Color.Red);
}
/* color commentaire // */
reg = new Regex("[^:]//[^\r\n]*", RegexOptions.Singleline | RegexOptions.Compiled);
for (regMatch = reg.Match(Text); regMatch.Success; regMatch = regMatch.NextMatch())
{
int nStart = regMatch.Index;
int nLenght = regMatch.Length;
UpdateContent(nStart, nLenght, Color.Green);
}
/* color commentaire multiligne */
reg = new Regex("/\\*([^*]|(\\*+([^*/])))*\\*+/", RegexOptions.Multiline | RegexOptions.Compiled);
for (regMatch = reg.Match(Text); regMatch.Success; regMatch = regMatch.NextMatch())
{
int nStart = regMatch.Index;
int nLenght = regMatch.Length;
UpdateContent(nStart, nLenght, Color.Green);
}
}
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
ColorSystaxe(Text);
}
protected override void OnTextChanged(EventArgs e)
{
base.OnTextChanged(e);
/*
- arrete le traitement si l'analise est dejas en cours
- /
if (th != null && th.IsAlive)
return;
/*
- lance l'analyse dans un thread
- /
th = new Thread(new ParameterizedThreadStart(ColorSystaxe));
th.IsBackground = true;
th.Start(Text);
}
}
}
Conclusion :
je suis ouvert au remarque , essayé le !
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.