Syntaxhighlighting - RTF
von Manuel Wessing
Übersicht
In diesem Tutor soll beschrieben werden, wie das Einfärben eines Wortes in der Richtextbox abläuft. Diese Methode ähnelt dem vom Visual Basic oder Visual C++, und zeigt auch dasselbe Verfahren.
Mit freundlichen Grüßen
Manuel Wessing m.wessing@boss-dortmund.de
Allgemeines
Gedanklich gesehen ist es eine einfache Idee ein Wort aus dem Text zu nehmen und die Wörter zu prüfen, und daraufhin einzufärben. Stellt man sich aber vor, dass der Text aus weit über 2000 Wörter besteht und bei jedem Tastendruck der komplette Text überprüft wird, steht man schnell vor einem Performanceproblem.
Immer nur das letzte Wort zu prüfen ist auch keine besonders gute Idee, wenn der Benutzer einmal in ein bereits geschriebenes Wort etwas ändert, ist die neue Einfärbung nicht gegeben.
Die Methode die hier beschrieben ist, prüft nur das Wort wo sich der Cursor gerade befindet. Als erstes sollten Sie eine Form anlegen und die RichTextBox darauf platzieren. Bitte benennen Sie diese in RTF1 um. Legen Sie weiterhin eine Modul Datei an.
Das Modul
Erst einmal sollten die Wörter definiert werden, die eine farbliche Kennzeichnung erhalten, die Erstellung einer Keywordlist ist dabei von Vorteil. Sie kann auch von einer Datei geladen werden.
Dies wird in das Modul eingetragen:
Public Type CONST_Keywords Color As Long Keyword As String End Type Public KeyWordlist(2) As CONST_Keywords Public Source As String
Es werden später zwei Wörter eingegeben, die eine Einfärbung erhalten (KeyWordlist(2)). Die Farbe wird in Color gespeichert. Die Zeichenfolge Source enthält den Text des RTF Steuerelements als eine Kopie. Dies ist besonders bei MDI Anwendungen interessant.
Form_Load
Folgenden Code bitte im Form_Load Ereignis eingeben:
KeyWordlist(1).Keyword = "Start" KeyWordlist(1).Color = vbBlue KeyWordlist(2).Keyword = "End" KeyWordlist(2).Color = vbRed
Für jedes Wort kann eine bestimmte Farbe definiert werden. Es spielt später keine Rolle, ob der Benutzer das Wort klein oder groß schreibt; es wird immer nach dieser Vorgabe geändert. Der wichtige Programmteil steht im RTF1_KeyUp Ereignis der RichTextBox. Das Programm soll nur Zeichen anzeigen wenn die Taste bereits gedrückt wurde.
RTF_KeyUP - das Wichtigste!
Als vorbereitung sollte im KeyUp Ereignis des RTF1 folgende Variablen definiert werden:
Dim BeginWort As Long Dim EndWort As Long Dim AltPos As Long Dim Pos As String Dim Wort As String Dim Char As String * 1
Los geht's ...
Das RTF Steuerelement hätte durch das Überprüfen des aktuellen Wortes und durch die ständige Einfärbung keine Möglichkeit Textteile mit der Tastatur zu markieren. Die Markierung würde immer direkt aufgehoben, da das Programm eine eigene Markierung einsetzt und dadurch die Textfarbe ändert.
Als erstes muss also auf Steuerzeichen für den Cursor geachtet werden. Zum Beispiel Pfeiltasten oder Pfeiltasten in Verbindung mit der Shift Taste. Der Folgende Programmteil prüft vorab ob es sich um eine Steuertaste handelt.
If (KeyCode > 33 And KeyCode < 40) Or (KeyCode > 33 And _ KeyCode < 40 And Shift = 1) Or KeyCode = 16 Then Exit Sub End If
Mit diesem Programmteil werden die Pfeilstasten und die Pos1 und Ende Taste mit Shift als auch ohne überprüft. Es wird also keine Wortprüfung stattfinden. So kann der Benutzer den Text mit der Tastatur selber markieren.
Als nächstes sollte der Text in die zweite Variable kopiert werden:
Source = RTF1.Text
Wenn es sich um eine MDI Anwendung handelt, kann hier die Übergabe an eine Collection sehr hilfreich sein.
Die wichtigste Information ist die aktuelle Cursor Position im Text. Diese wird mit der Eigenschaft SelStart ermittelt. Und in eine Lokale Variable gespeichert. Da die Cursor-Position verändert wird, brauchen wir eine Kopie der Cursor-Position, um den Cursor später wieder dort hinzubringen:
AltPos = RTF1.SelStart Pos = AltPos
Das Erkennen eines Wortes ist in der Regel sehr einfach. Als erstes sucht das Programm nach dem Beginn des Wortes. Dabei sucht das Programm nach einem Trennzeichen. Ein Satz wird in einer Sprache meist durch ein Leerzeichen ( Engl. Space ) getrennt. Dieses Zeichen wird gesucht. Neben bei gibt es in einer Zeichenfolge keine Zeilenumbrüche. Ein Zeilenende wird mit Chr(13) & Chr(10) abgeschlossen. Nach diesen Zeichen wird weiterhin gesucht. Hier können auch weitere Zeichen eingetragen werden, wie ( oder ). Geachtet werden muss auch auf das Antreffen des Anfangs der Zeichenfolge. Wenn der Cursor Position -1 erreicht, beginnt logischerweise das Wort bei Position 0. Im RTF beginnt das erste Zeichen bei 0.
Do If Pos > 0 Then Char = Mid(Source, Pos, 1) Else BeginWort = 1 Exit Do End If If Char = " " Or Char = Chr(10) Or Char = Chr(13) Or Pos = -1 Then BeginWort = Pos + 1 Exit Do End If Pos = Pos - 1 Loop Until Pos < 0
Im Gegenzug muss auch das Ende des Wortes gesucht werden. Hier wird auch wieder auf ein Leerzeichen oder auf ein Zeilenende gesucht. Natürlich muss auch darauf geachtet werden ob das Ende der Zeichenfolge erreicht wurde.
Do Pos = Pos + 1 If Pos <= Len(Source) Then Char = Mid(Source, Pos, 1) Else EndWort = Len(Source) + 1 Exit Do End If If Char = " " Or Char = Chr(10) Or Char = Chr(13) Or _ Pos > Len(Source) Then EndWort = Pos Exit Do End If Loop Until Pos < 0
In den Variablen BeginWort und EndWort stehen nun die Start- und End-Positionen des Wortes unter dem Cursor.
Hier ist das Prinzip noch eimal erklärt.
Im ersten Schritt wird der Anfang des Wortes gesucht. (| = Cursor)
Hallo,dies ist ein S|atz
Der Cursor steht an Position 20. Das Programm wandert nun ein Zeichen zurück auf die 19, es erkennt dort kein Wortende und geht wieder einen Schritt zurück auf die 18. Dort wurde ein Leerzeichen gefunden. Somit muss also 19 der Anfang des Wortes sein. Das andere Verfahren ist ähnlich nur wird hier die Position immer um 1 erhöht.
Damit keine Überraschungen auftreten und sich der Cursor zwischen zwei Leerzeichen steht muss vorher eine Abfrage stattfinden:
If BeginWort > -1 And EndWort > -1 And (EndWort > BeginWort) Then
Nun kann es daran gehen, das Wort aus dem Text zu nehmen und es zu vergleichen:
Wort = Mid(Source, BeginWort, EndWort - BeginWort)
Nun ist das Wort bekannt, wo sich der Cursor befindet. Nun kann es auf Richtigkeit überprüft werden:
If Wort <> "" Then KeyWordColoring Wort, BeginWort RTF1.SelStart = AltPos RTF1.SelLength = 0 RTF1.SelColor = vbBlack End If
Es wird eine Sub Routine benutzt, um die Textstelle zu markieren und sie einzufärben. Der Cursor wird später wieder an die alte Textstelle gesetzt und die Farbe auf Schwarz geschaltet.
Hier der Quellcode der Routine KeyWordColoring:
Private Sub KeyWordColoring(Word As String, BeginWord As Long) Dim Color As Long For t = 1 To UBound(KeyWordlist) If UCase(Word) = UCase(KeyWordlist(t).Keyword) Then Color = KeyWordlist(t).Color Found = t Exit For Else Color = vbBlack Found = 0 End If Next 't RTF1.SelStart = BeginWord - 1 RTF1.SelLength = Len(Word) RTF1.SelColor = Color If Found > 0 Then RTF1.SelText = KeyWordlist(t).Keyword End If End Sub
Es werden alle Einträge der KeyWordList() abgearbeitet. Wurde das Wort in der Liste gefunden, wird die Position im RTF markiert und eingefärbt. Dazu wird noch die Schreibweise angepasst. Ist das Wort nicht in der Liste ( Found = 0 ) wird der Text Schwarz gezeichnet. Das Einfärben geschieht auch dann wenn das Wort bereits einmal eingefärbt wurde.
Download
Hier können Sie ein Beispielprojekt downloaden.
Anmerkung: ActiveVB hat sich die Freiheit genommen, eine Liste der Visual-Basic-Schlüsselwörter in das Projektbeispiel einzubinden.
Beispielprojekt [3596 Bytes]
Ihre Meinung
Falls Sie Fragen zu diesem Tutorial haben oder Ihre Erfahrung mit anderen Nutzern austauschen möchten, dann teilen Sie uns diese bitte in einem der unten vorhandenen Themen oder über einen neuen Beitrag mit. Hierzu können sie einfach einen Beitrag in einem zum Thema passenden Forum anlegen, welcher automatisch mit dieser Seite verknüpft wird.