Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 17 - Tvoříme vlastní Syntax Highlighter pomocí RichTextBox v C#

V předchozích 4 lekcích jsme pracovali se základními ovládacími prvky, které nabízí sám .NET Framework. Toto počínání jsme dovršili lekcí Ovládací prvky Windows Forms počtvrté.

V dnešním C# .NET Windows Forms tutoriálu naprogramujeme vlastní Syntax Highlighter, tedy zvýrazňovač syntaxe v C# .NET, jako má např. Visual Studio. Procvičíme si tím použití ovládacího prvku RichTextBox:

Syntax highlighter v C# .NET - Windows Forms - Okenní aplikace v C# .NET

Návrh

Nejprve je třeba si rozvrhnout, jak vlastně bude náš program fungovat. Nejjednodušší, co určitě většinu z vás napadne, je mít nějakou kolekci s klíčovými slovy a jejich barvou, tu projet cyklem a podle toho text obarvovat. A přesně tak to i uděláme. Samozřejmě nesmíme očekávat extra výkon a chtít zvýrazňovač použít pro dlouhý kód. Hodí se spíše pro jednorázové zvýraznění. Ale my si vyzkoušíme i realtime. Efektivní zvýraznění bychom museli udělat pomocí tokenizace, což je nad rámec tohoto kurzu.

Návrh formuláře

Vytvoříme si novou Windows Forms aplikaci s názvem EasySyntaxHighlighter. Začneme tradičně návrhem formuláře. Přidáme do něj ovládací prvky:

  • RichTextBox na kód ke zvýraznění a
  • Button na zapnutí zvýraznění, realtime zvýraznění si totiž pro zjednodušení přidáme až později.

RichTextBox bude moci psát odsazení tabulátorem, proto mu povolíme AcceptsTab. Tlačítku vytvoříme událost OnClick.

Slovníky

Nyní si vytvoříme třídu SyntaxHighlighter.

Vytvoření slovníku

Přidáme do ní statickou kolekci keywords typu Dictionary s typem klíče string a hodnotou Color:

private static Dictionary<string, Color> keywords;

Dále přidáme veřejnou statickou metodu void InitializeKeywords(), ve které kolekci inicializujeme a vložíme do ní naše klíčová slova. Můžeme přidat také jednoduché ošetření if (keywords != null) return;, aby metoda zbytečně neproběhla vícekrát.

Statická je kolekce a metoda proto, že tato klíčová slova budou vždy stejná a je zbytečné ukládat je pro každou instanci highlighteru.

Naplnění slovníku

Najdeme si klíčová slova, která budeme zvýrazňovat. Budeme zvýrazňovat samozřejmě klíčová slova C#.

Klíčová slova z daných odkazů jednoduše zkopírujeme a v textovém editoru ořežeme tak, aby z nich vznikl dlouhý řádek jednotlivých slov oddělených čárkou, jako:

abstract,event,new,struct,as,explicit,null,switch,base,extern,this,false,operator,throw,break...

Teď je třeba smazat duplicitní slova. To můžeme udělat buď ručně nebo si na to napsat malý C# program, který slova rozdělí podle čárky, cyklem přidá do kolekce List a pak zavolá Distinct().

Klíčová slova je pak dobré roztřídit. Budeme rozlišovat jinou barvou datové typy a jinou ostatní klíčová slova. Klíčová slova budou třeba zelená, kdežto datové typy modré.

Ve výsledku dospějeme k následujícím řetězcům, které slova definují. Pokud se vám nechce sestavovat si tyto definice ručně, můžete si jen zkopírovat tyto proměnné. Vložíme je dále do metody InitializeKeywords():

string CSharpKeywords = "abstract,event,new,struct,as,explicit,null,switch,base,extern,this,false,operator,throw,break,finally,out,true,fixed,override,try,case,params,typeof,catch,for,private,foreach,protected,checked,goto,public,unchecked,if,readonly,unsafe,implicit,ref,continue,in,return,using,virtual,default,interface,sealed,volatile,delegate,internal,do,is,sizeof,while,double,lock,stackalloc,else,static,namespace";
string DataTypes = "bool,object,byte,float,class,uint,char,ulong,ushort,const,decimal,int,sbyte,short,void,long,enum,string";

No a teď už jen jednoduše projedeme cyklem jednotlivá slova a přidáme je do kolekce s příslušnou barvou:

foreach (string word in CSharpKeywords.Split(','))
    keywords.Add(word, Color.Green);

foreach (string type in DataTypes.Split(','))
                keywords.Add(type, Color.Blue);

Tuto metodu zavoláme v konstruktoru formuláře, který v něm již máme:

public Form1()
{
    InitializeComponent();

    SyntaxHighlighter.InitializeKeywords();
}

Zvýraznění

Nyní se přesuneme zpět do třídy SyntaxHighlighter. Přidáme sem veřejnou statickou metodu HighlightText(), která vrací string a jejím parametrem je string text.

Metoda je opět statická, protože SyntaxHighlighter nenese žádná instanční data, je to jen takový pomocník. Jestli chcete, můžete si celou třídu označit jako static.

V metodě si vytvoříme další pomocnou instanci RichTextBox, ve které si zvýrazněný dokument připravíme:

RichTextBox rtb = new RichTextBox();
rtb.Text = text;
rtb.Font = new Font(FontFamily.GenericMonospace, 8.75f, FontStyle.Regular);

Obarvení klíčových slov

Dále projedeme všechna klíčová slova, vyhledáme je v textu a obarvíme příslušnou barvou:

int index;
foreach (var entry in keywords)
{
    index = 0;
    while ((index = rtb.Find(entry.Key, index, RichTextBoxFinds.WholeWord)) != -1)
    {
        rtb.Select(index, entry.Key.Length);
        rtb.SelectionFont = new Font(rtb.Font.FontFamily, rtb.Font.Size, FontStyle.Bold);
        rtb.SelectionColor = entry.Value;
        index += 1;
    }
}

Proměnná index určuje současnou pozici v textu. Při hledání dalšího slova se postupuje od pozice toho předchozího. Přičítá se k němu 1, protože je v něm obsažena pozice, kde začíná dané slovo a program by se zacyklil. Takto slovo usekneme a bude se hledat dál.

Metoda Find() vyhledá dané slovo, začíná hledat od dané pozice a hledá pouze samostatná slova, tzn. např. "in" najde, ale "indeed" už ne. Vrátí pozici, kde dané slovo začíná. Pokud se v textu nevyskytuje, vrátí -1.

Metoda Select() vybere text, který začíná na dané pozici a označí zadaný počet znaků. Dělá to samé, jako když klepneme a táhneme myší přes text.

Nyní, když je text vybrán, zvolí se barva a písmo výběru pomocí SelectionFont a SelectionColor.

Můžeme si dále zvýraznit i komentáře:

index = 0;
while ((index = rtb.Text.IndexOf("//", index)) != -1)
{
    rtb.Select(index, rtb.Text.IndexOf("\n", index) - index);
    rtb.SelectionFont = new Font(rtb.Font.FontFamily, rtb.Font.Size, FontStyle.Regular);
    rtb.SelectionColor = Color.Gray;
    index += 2; // zde se přičítá dvojka kvůli popiskům tzv. summary, kde jsou /// závorky, já je beru jako komentář.
}

Nebo i string "můj text" či více řádkové komentáře /* můj komentář */, které lze jednoduše přidat stejným způsobem jako jednořádkový komentář (viz projekt ke stažení pod lekcí).

Testování

Nyní si zvýrazňovač vyzkoušíme. Pouze do události tlačítka přidáme:

richTextBox1.Rtf = SyntaxHighlighter.HighlightText(richTextBox1.Text);

A spustíme :)

Real-time zvýrazňování

Nyní si zkusíme real time zvýrazňování. Tzn., že budeme psát a bude se nám text ihned zvýrazňovat. Tlačítko smažeme i s událostí. RichTextBox nastavíme dock, aby se nám pěkně roztáhl. A přidáme mu událost KeyDown, kde zvýraznění zavoláme.

Pokud jste někteří zkoušeli s předstihem, narazili jste pravděpodobně na problém, že se vlastně nedá psát. Při zvýraznění se nám totiž kurzor začne vracet na začátek. Tento problém ošetříme jednoduše uložením současné pozice kurzoru SelectionStart, zvýrazněním textu a následným nastavením pozice kurzoru zpět. Kód obslužné metody pro událost KeyDown je tedy následující:

int lastSelectionStart = richTextBox1.SelectionStart;
richTextBox1.Rtf = SyntaxHighlighter.HighlightText(richTextBox1.Text);
richTextBox1.SelectionStart = lastSelectionStart;

Bystří z vás narazí na další problém, že pokud chceme něco označit a smazat, nejde to. To se dá snadno ošetřit kontrolou, zda je něco vybraného, tzn. délka výběru. Na začátek té samé obslužné metody přidáme:

if (richTextBox1.SelectionLength > 0) return;

A náš vlastní highlighter je na světě! V přiloženém archivu si můžete stáhnout verzi, která zvýrazňuje i textové řetězce a také jazyk PHP:

Windows Forms - Okenní aplikace v C# .NET

V příští lekci, Vlastní ovládací prvky v C# .NET, si ukážeme jak si vytvořit svůj vlastní ovládací prvek.


 

Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

Staženo 426x (49.16 kB)
Aplikace je včetně zdrojových kódů v jazyce C#

 

Předchozí článek
Ovládací prvky Windows Forms počtvrté
Všechny články v sekci
Windows Forms - Okenní aplikace v C# .NET
Přeskočit článek
(nedoporučujeme)
Vlastní ovládací prvky v C# .NET
Článek pro vás napsal David Jančík
Avatar
Uživatelské hodnocení:
15 hlasů
Autor je vášnivý programátor. Nezná slovo "nelze", nebojí se zkoušet nepoznané a pronikat do nových technologií.
Aktivity