RICHTEXTBOX D'EDITION C# AVEC COLORISATION SYTAXIQUE

KrocLeBo Messages postés 18 Date d'inscription jeudi 7 juin 2001 Statut Membre Dernière intervention 19 avril 2010 - 19 avril 2010 à 08:14
Whismeril Messages postés 19028 Date d'inscription mardi 11 mars 2003 Statut Non membre Dernière intervention 24 avril 2024 - 17 avril 2015 à 15:59
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/51632-richtextbox-d-edition-c-avec-colorisation-sytaxique

Whismeril Messages postés 19028 Date d'inscription mardi 11 mars 2003 Statut Non membre Dernière intervention 24 avril 2024 656
17 avril 2015 à 15:59
bonjour, où peut on trouver cette librairie tom ? merci
très bien
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
21 sept. 2010 à 11:48
J'ai amélioré la chose, en supprimant le scintillement, et en relookant un peu le code (exit UpdateColor...)
Je n'avais pas besoin des Keywords, a vous de les remettre...

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Threading;
using tom;

namespace TextDefinitionWindow {
class RichTextBox : System.Windows.Forms.RichTextBox {
private struct ColorItem {
public Regex Regex;
public Color Forecolor;

public ColorItem(String vsPattern, RegexOptions veRegexOptions, Color veForeColor) {
Regex = new Regex(vsPattern, veRegexOptions | RegexOptions.Compiled);
Forecolor = veForeColor;
}
}

private Thread th = null;
private bool InternalChange = false;
private List<ColorItem> ColorItems = new List<ColorItem>();

public RichTextBox() {
}

#region WIN32
[DllImport("User32.dll")]
private static extern int SendMessage(IntPtr hWnd, int message, IntPtr wParam, out IntPtr lParam);

private const int EM_GETOLEINTERFACE = WM_USER + 60;
private const int WM_USER = 0x0400;
#endregion

#region TOM OBJECT MODEL
private ITextDocument _oTextDocument = null;
private ITextDocument TextDocument {
get {
if (_oTextDocument == null)
_oTextDocument = Create();
return _oTextDocument;
}
set {
if (_oTextDocument != null)
Marshal.ReleaseComObject(_oTextDocument);
_oTextDocument = value;
}
}

private ITextDocument Create() {
IntPtr oRichEditOle = IntPtr.Zero;
if (SendMessage(base.Handle, EM_GETOLEINTERFACE, IntPtr.Zero, out oRichEditOle) == 0)
throw new System.ComponentModel.Win32Exception();
try {
return (ITextDocument)Marshal.GetTypedObjectForIUnknown(oRichEditOle, typeof(ITextDocument));
}
finally {
Marshal.Release(oRichEditOle);
}
}

private delegate void SetForecolorDelegate(int vnStart, int vnLength, Color veForecolor);
private void SetForecolor(int vnStart, int vnLength, Color veForecolor) {
if (this.InvokeRequired)
this.Invoke(new SetForecolorDelegate(SetForecolor), new Object[] { vnStart, vnLength, veForecolor });
else {
ITextRange Range = TextDocument.Range(vnStart, vnStart + vnLength);
int ForeColor = ColorTranslator.ToOle(veForecolor);
// On n'appelle le coloriage que si nécessaire
if (Range.Font.ForeColor != ForeColor) {
InternalChange = true;
//TextDocument.Freeze();
Range.Font.ForeColor = ForeColor;
//TextDocument.Unfreeze();
InternalChange = false;
}
}
}
#endregion

public void SyntaxColor(object data) {
String Text = data as String;

// Permettra de mettre en noir le texte neutre.
List ColoredItems = new List();
ColoredItems.Add(0);
ColoredItems.Add(Text.Length);

foreach(ColorItem Item in ColorItems)
foreach (Match Match in Item.Regex.Matches(Text)) {
ColoredItems.Add(Match.Index);
ColoredItems.Add(Match.Index + Match.Length);
// On supprime le texte de l'item de la variable Texte.
Text = Text.Substring(0, Match.Index) + new String(' ', Match.Length) + Text.Substring(Match.Index + Match.Length);
SetForecolor(Match.Index, Match.Length, Item.Forecolor);
}

// On colorie en noir le texte restant
ColoredItems.Sort();
int[] TextIndexes = ColoredItems.ToArray();
for (int i = 0; i + 1 < TextIndexes.Length; i += 2)
SetForecolor(TextIndexes[i], TextIndexes[i + 1] - TextIndexes[i], Color.Black);
}

protected override void OnHandleCreated(EventArgs e) {
base.OnHandleCreated(e);

// J'ai plus ou moins laissé les Regexp, il faudrait les blinder un peu...
/* color commentaire // */
ColorItems.Add(new ColorItem("//[^\r\n]*", RegexOptions.Singleline, Color.Green));
/* color commentaire multiligne */
ColorItems.Add(new ColorItem("/\\*[\\s\\S]\\*/", RegexOptions.Multiline, Color.Green));
/* color string */
ColorItems.Add(new ColorItem(""[^\\\\]"", RegexOptions.Singleline, Color.Red));
SyntaxColor(base.Text);
}

protected override void OnTextChanged(EventArgs e) {
// Ne se déclenche pas pendant notre coloriage
if (!InternalChange) {
base.OnTextChanged(e);
if (th != null && th.IsAlive) {
// Plutot que de sortir (notre appel etant justifié)
// on annule le thread de coloriage en cours
th.Abort();
// On s'assure de l'efficacité de notre dernier appel
while (th.ThreadState != ThreadState.Stopped)
Thread.Sleep(1);
}
th = new Thread(new ParameterizedThreadStart(SyntaxColor));
th.IsBackground = true;
th.Start(Text);
}
}
}
}
TheManu Messages postés 8 Date d'inscription jeudi 26 juillet 2007 Statut Membre Dernière intervention 11 mai 2010
6 juin 2010 à 13:29
autant pour moi je ne l'avais pas vu. Merci
yohan49 Messages postés 380 Date d'inscription samedi 22 janvier 2005 Statut Membre Dernière intervention 13 août 2011 7
4 juin 2010 à 22:52
salut il faut ajouter la reference COM tom
TheManu Messages postés 8 Date d'inscription jeudi 26 juillet 2007 Statut Membre Dernière intervention 11 mai 2010
4 juin 2010 à 17:32
Salut,
Comment tu récupères la référence à 'ITextDocument' pour .NET (j'ai cru comprendre que c'est une interface Windows) ? De même pour 'ITextRange' ? 'using tom' ?
Merci :)
yohan49 Messages postés 380 Date d'inscription samedi 22 janvier 2005 Statut Membre Dernière intervention 13 août 2011 7
19 avril 2010 à 11:06
salut

bien vu KrocLeBo, je n'y avais pas pensé ! merci :)
j'essais actuellement de rajouté la colorisation syntaxique sur les types mais c franchement pas evident
KrocLeBo Messages postés 18 Date d'inscription jeudi 7 juin 2001 Statut Membre Dernière intervention 19 avril 2010
19 avril 2010 à 08:14
Pour éviter scintillement en édition, voici quelques optimisations :

- Utiliser des variables statiques pour les regx, initialisées une seule fois (gros gain de temps)
- Quand c'est possible utiliser l'option ExplicitCapture (ça accélère un peu le traitement)

Voici une partie de code modifée (chez moi plus de scintillement après ça)

public class RichEditorCsharp : RichTextBox
{
static readonly Regex regString = new Regex("(@"|")[^"]*(?:\\\\.[^"]*)*"", RegexOptions.Multiline | RegexOptions.Compiled);
static readonly Regex regCommentSingle = new Regex("[^:]//[^\r\n]*", RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.ExplicitCapture);
static readonly Regex regCommentMultiple = new Regex("/\\*([^*]|(\\*+([^*/])))*\\*+/", RegexOptions.Multiline | RegexOptions.Compiled);
static Regex regKeywords;

... / ...

public void ColorSystaxe(object data)
{
String Text = data as String;
Match regMatch;

UpdateContent(0, Text.Length, Color.Black);

/* color mot clé */for(regMatch regKeywords.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 @*/for(regMatch regString.Match(Text); regMatch.Success; regMatch regMatch.NextMatch())
{
int nStart = regMatch.Index;
int nLenght = regMatch.Length;
UpdateContent(nStart, nLenght, Color.Red);
}

/* color commentaire // */for(regMatch regCommentSingle.Match(Text); regMatch.Success; regMatch regMatch.NextMatch())
{

int nStart = regMatch.Index;
int nLenght = regMatch.Length;
UpdateContent(nStart, nLenght, Color.Green);
}

/* color commentaire multiligne */for(regMatch regCommentMultiple.Match(Text); regMatch.Success; regMatch regMatch.NextMatch())
{
int nStart = regMatch.Index;
int nLenght = regMatch.Length;
UpdateContent(nStart, nLenght, Color.Green);
}
}
Rejoignez-nous