Richtextbox: Manuell eingegebener Text soll andere Farbe haben

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 23 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    Richtextbox: Manuell eingegebener Text soll andere Farbe haben

    Hallo zusammen,

    aktuell spiele ich mit RTB rum und schaue mir an was möglich ist, und vor allem was ich programmiert bekomme.
    Soweit ich nun verstanden habe, hat eine RTB (unter anderem) 2 Vorteile.
    • Ich kann den Text formatieren
    • Ich kann aktiv darin den Text ändern

    Ich habe nun schon einiges probiert, einiges gelesen und auch einiges hat funktioniert.
    Texte farbig machen, bestimmte Stellen einfärben, das klappt soweit. Es klappt auch nach Schlagworten zu suchen und diese farblich zu markieren, oder die ganze Zeile in der das Schlagwort steht.

    Nun ein Punkt will nicht gelingen. Ich finde auch per Suche nichts was auf exakt DIESES Problem hinauslaufen würde. Und auch eine schlüssige Logik wie ich das grundsätzlich lösen mag ergab sich bisher nicht.
    Ich habe also eine RTB. In diese wird automatisch Text geschoben, sei es nun per Import aus einer ext. Quelle oder aus dem Programmcode selbst. Dieser ist im nicht weiter veränderten Zustand schwarz und weder fett noch kursiv noch sonstwas.
    Das ist soweit auch ok.
    Nun kann ichja aber auch manuell in diesen Text eingreifen. Ich kann Stellen löschen und neu schreiben. Oder ich ergänze Text. Und eben diesen manuell bearbeiteten Text, den hätte ich gerne in einer anderen Farbe, so dass ich direkt sehe welche Teile vom Programm generiert oder eingelesen wurden, und was von Hand gemacht wurde.

    Ums mal mit einem ganz einfachen Beispiel zu hinterlegen:

    Das hier ist ein willkürlicher Text der vom Programmcode in die RTB geschoben wird:
    Das hier ist mein Text in der RTB. Dieser wurde im Programm Code fest hinterlegt und in die RTB geschrieben.
    Alternativ könnte er auch durch das Programm aus einer externen Datei eingelesen worden sein. Die Schrift ist Standard und schwarz.
    Hier könnten auch noch so tolle Dinge wie "Hallo Welt" stehen.


    Nun greife ich manuell ein und mache den (sinnfreien) Inhalt anders:
    Das hier ist mein Text in der RTB. Dieser wurde im Programm Code fest hinterlegt und in die RTB oder sollen wir es lieber übertragen nennen?
    Alternativ könnte er auch durch das Programm aus einer externen Datei eingelesen worden sein. Die Schrift ist Standard und schwarz außerdem ist sie weder fett noch kursiv o.ä.
    Hier könnten auch noch so tolle Dinge wie "Halloele Welt" stehen, das ist allerdings kein Muss.


    Ich weiß, das Beispiel ist schwer sinnbefreit :D
    Ich hoffe aber, das Prinzip wird klar, ich möchte einfach auf einen Blick sehen was der ursprünglich vom Programm übergebene Text ist, und was manuelles User - Gequassele ist.

    Vom Prinzip her ist es ähnlich wie folgendes Beispiel:
    Stellt euch vor, ein Kumpel schreibt eine Abschlussarbeit, alles in s/w ohne Ausnahmen.
    Am Ende bittet er euch Rechtschreibung, Grammatik, Satzbau und Formulierung zu korrigieren.
    Da es nicht eure Arbeit ist, und ihr nur Tipps gebt, macht ihr alle Anmerkungen und Änderungen rot&fett, damit der Kumpel sie direkt sieht und selbst entscheiden kann.

    "...Während er euch dann so einen schlechten Text geben tut, weil der nähmlich total mies formuliert ist..."
    bekommt er von euch dann das zurück:
    "...Während er euch dann so einen schlechten Text (geben tut) gibt, weil der nähmlich total mies formuliert ist..."

    So, ich hoffe mal, dass ich ausdrücken konnte um was es mir geht, denn oftmals hängt es ja schon daran, dass man sein Problem nicht richtig beschreiben kann.

    Ich habe mir überlegt, dass man vielleicht diese Textformatierung "rot & fett" an den Cursor binden kann, dass zum Beispiel stets die Zelle vor dem Cursor so definiert ist. Dann würde man ja beim Schreiben diese Textformatierung fließend vor sich herschieben.
    Allerdings habe ich keinen Schimmer ob das Sinn macht, ob das funktioniert, oder wie es gehen könnte.
    Ich habe feste Textteile formatiert, ich habe gesucht und diese statische Stelle formatiert, ich habe auch Codes gefunden wie man den Cursor sucht. Aber ich kriege es eben nicht hin, weder praktisch, noch von der Theorie her, wie man das auf meinen Wunsch anwenden könnte?

    Habt ihr eine Idee?
    Du brauchst dafür nur das SelectionChanged-Ereignis deiner RTB nehmen und in diesem Ereignis behandelst du dann die Eigenschaften der RTB SelectionFont und SelectionColor nach deinen Vorstellungen.
    Der Beispiel-Code unten benötigt in einer Form eine RichtextBox und eine Checkbox...

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private fnt As Font = New Font("Arial", 8, FontStyle.Regular)
    3. Private col As Color = Color.Black
    4. Private Sub Richtextbox_SelectionChanged(sender As Object, e As EventArgs) Handles myRTB.SelectionChanged
    5. myRTB.SelectionFont = fnt
    6. myRTB.SelectionColor = col
    7. End Sub
    8. Private Sub Combobox_CheckedChanged(sender As Object, e As EventArgs) Handles cbxSpellCheck.CheckedChanged
    9. If cbxSpellCheck.Checked Then
    10. fnt = New Font("Arial", 12, FontStyle.Bold)
    11. col = Color.Red
    12. Else
    13. fnt = New Font("Arial", 8, FontStyle.Regular)
    14. col = Color.Black
    15. End If
    16. End Sub
    17. End Class

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VB1963“ ()

    @Spawnie Meinst Du so was wie die Änderungsverfolgung in Word?
    Probier mal dies, allerdings musst Du noch unterscheiden zwischen Einfügen und Überschreiben usw.:

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private Manuell As Boolean = False
    3. Private Sub RichTextBox1_KeyDown(sender As Object, e As KeyEventArgs) Handles RichTextBox1.KeyDown
    4. If e.KeyCode >= Keys.A AndAlso e.KeyCode <> Keys.Z Then ' hier die Liste Deiner Buchstaben einfügen
    5. Me.Manuell = True
    6. Me.RichTextBox1.SelectionColor = Color.Red
    7. Me.RichTextBox1.SelectionLength = 1
    8. End If
    9. End Sub
    10. Private Sub RichTextBox1_KeyPress(sender As Object, e As KeyPressEventArgs) Handles RichTextBox1.KeyPress
    11. If Me.Manuell Then
    12. Me.RichTextBox1.SelectionColor = Color.Red
    13. Me.RichTextBox1.SelectionLength = 1
    14. End If
    15. End Sub
    16. Private Sub RichTextBox1_KeyUp(sender As Object, e As KeyEventArgs) Handles RichTextBox1.KeyUp
    17. If Me.Manuell Then
    18. Me.RichTextBox1.SelectionLength = 0
    19. Me.RichTextBox1.SelectionColor = Color.Black
    20. Me.Manuell = False
    21. End If
    22. End Sub
    23. End Class
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Vorweg eine andere Farb - Frage die sich ergeben hat:
    Wie ich ja gesagt habe, ich suche Schlagwörter und färbe diese ein. Nehmen wir mal an, ich will das Wort "Achtung" rot haben.
    Das klappt soweit, nur ergibt sich dabei beim manuellen editieren eine unsaubere Gegebenheit.
    Es soll nur die Zeile mit dem "Achtung" rot sein. Wenn ich aber unter diesem "Achtung" etwas einfügen möchte, und dazu hinter das "Achtung" klicke und Enter für eine neue Zeile drücke, dann wird der Text da auch rot&fett.
    Gewünscht wäre aber "schwarz&normal". Es wird also die Formatierung der eingefärbten Zeile vererbt, vermutlich weil ich dort mit dem Cursor hinklicke um per Enter Raum zu schaffen.
    Ich habe dazu mal ein Bild hochgeladen. Eigentlich sollte nur das ACHTUNG rot sein, aber auch mein manueller Text aus der Folgezeile ist rot geworden.



    Wobei dieses Problem aber auch gelöst wäre, wenn alle manuelle Eingaben zwingend eine bestimmte Formatierung hätten.





    So, nun zum Einfärben des manuell eingegebenen Textes.
    Um erhlich zu sein, ich hab die Änderungsverfolgung bei Word noch nie genutzt, kann also nicht sagen obs in die Richtung geht :|
    Ich kanns nur ganz banal erklären. Du - das Programm - schreibst mir nen Brief. Mit deinem schwarzen Kulli 8o
    Dann bekomme ich - der User - den Brief und kritzel drin rum. Ich hab aber nur nen blauen Stift.
    Wenn nun wer den Brief sieht und Bescheid weiß, weiß er direkt was dein ursprünglicher Inhalt war, und was meine Ergänzungen sind.

    Optimal wäre natürlich eine Lösung bei der man dem Programm beibringt zwischen autom. erzeugtem Text und manueller Eingabe über das Keyboard zu unterscheiden und demnacht den Text zu färben.

    Aber VB1963 hat mich auf eine andere Idee gebracht mit seinem Schalter. Das wäre zwar keine allgemeingültige Lösung, aber in meinem speziellen Fall würde es ausreichen.
    Ich überlege gerade folgenden Ansatz:
    Das Programm läuft ja nicht willkürlich ab sondern geht Befehl für Befehl durch den Code, was bei mir ungefähr so aussieht:
    1. Button Click, neue Form mit RTB öffnet sich
    2. RTB wird automatisch vom Programm beschrieben
    3. X
    4. User ändert manuell den Text
    Im ersten Schritt wird der Text automatisch in die RTB gepackt, dieser soll ja schwarz sein.
    Sobald das erledigt ist, kommt es bei mir in keinem Fall mehr zu einem autom. Input. Alle Änderungen die von nun an erfolgen könnten sind ausschließlich manuell.
    Und vielleicht kann man ja da ansetzen?
    Wenn ich beim Schritt X es einrichten könnte, dass alles was von nun an folgt blau&fett ist und unter keinen Umständen mehr anders formatiert werden kann, dann wäre mein Ziel erreicht.
    Gut mein Programm wäre immer noch nicht in der Lage manuell von automatisch zu unterscheiden, aber das macht in dem Fall ja nix. Aus Sicht des Ablaufs kann zu diesem Zeitpunkt nur noch manuelles Material kommen, also könnte man grundlegend umschalten.
    Wäre das machbar indem ich nach dem Programmteil der den autom. Text erzeugt das Format auf Blau&Fett umstelle?
    Bilder
    • Unbenannt.JPG

      22,94 kB, 475×210, 624 mal angesehen

    Spawnie schrieb:

    Wäre das machbar indem ich nach dem Programmteil der den autom. Text erzeugt das Format auf Blau&Fett umstelle?
    Also das Umstellen der Textfarbe passiert in meinem obigen Beispiel im CheckedChange-Event der Combobox. Wenn du diese Combobox nicht haben willst, dann mache das nach dem Laden des Textes in die RTB...
    Ich habe dir mein obiges Beispiel einmal angehängt - das tut eigentlich das, was du machen möchtest. Nur halt mit der Combobox - die kannst du ja wegmachen...
    Dateien
    Ich habe dein Beispiel mal in mein Programm ergänzt und versucht um die Checkbox zu erleichtern.
    Ich hatte es auch soweit, dass mein manuell geschriebener Text blau war, allerdings wurden auch - für mich willkürliche - Teile des original Textes blau eingefärbt.

    Vielleicht habe ich die Checkbox nicht sauber entfernt...

    Habt ihr vielleicht auch zu dem zweiten Problem eine Idee?
    Wie ich die "Vererbung" der Farbe und des Styles umgehen kann wenn ich mir mit ENTER eine Zeile Luft unter einer farbigen Zeile schaffe?

    Das einfärben bestimmter Zeilen mit Schlagwörtern habe ich bislang mit diesem Code - Schnipsel den ich gefunden hatte ausprobiert:

    VB.NET-Quellcode

    1. Dim rtbLines2() As String = FTEdit.RichTextBox1.Lines
    2. Dim redi As Integer
    3. For redi = 0 To rtbLines2.GetUpperBound(0)
    4. If rtbLines2(redi).Contains("ACHTUNG") Then
    5. FTEdit.RichTextBox1.SelectionStart = FTEdit.RichTextBox1.GetFirstCharIndexFromLine(redi)
    6. FTEdit.RichTextBox1.SelectionLength = rtbLines2(redi).Length
    7. FTEdit.RichTextBox1.SelectionColor = Color.Red
    8. FTEdit.RichTextBox1.SelectionFont = New Font(FTEdit.RichTextBox1.Font, FontStyle.Bold)
    9. End If
    10. Next
    11. End Sub


    Das wäre schon mal ein wichtiger Schritt, diese doofe "Vererbung".

    Und wenn ich dann noch den blauen User - Stift hin bekäme....
    Aber eins nach dem anderen.
    Vermutlich wäre es sinnvoll die Farb - Spielereien die ich schon habe erst mal zu zügeln, dass sie so laufen wie ich möchte, bevor ich anfange weitere Farben in den Topf zu mischen.
    @Spawnie Hast Du meinen Post #3 ignoriert?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @RodFromGermany Nein habe ich nicht. Allerdings war ich mir nicht ganz sicher, was der Code macht.
    Ich konnte nicht wirklich nachvollziehen was die 3 Subs KeyPress, KeyUp und KeyDown im einzelnen tun und für was man welche braucht.

    Ich habs daher mal in eine Form gepackt die nix außer einer RTB hat.
    Die Buchstaben A bis Y sind rot, Z, die Zahlen und alle Sonderzeichen sind schwarz. Da ich ja aber grundsätzlich ALLES in einer Farbe schreiben wollen würde, kam ich auch bei der Frage "wie erweitere ich die Buchstabenliste A - Z , zumal ja auch Z fehlt".
    Wenn ich schnell tippe, habe ich zudem Vermischungen, schwarze Buchstaben oder rote Zahlen, also entweder überlappt sich dort was, oder es gibt einen von mir noch nicht gefundenen Trigger für die Farbe.

    Von daher hatte ich da halt eben 0 Ideen wie ich das auf mich anwenden könnte :|

    Spawnie schrieb:

    zumal ja auch Z fehlt
    OMG.
    Da bist Du ja voll in meine C&P-Bremse gelaufen und hast gar nichts verstanden bzw. zu verstehen versucht. :D
    Sieh Dir mal die Zeile 5 in meinem Snippet an, sie beinhaltet auch einen Kommentar.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ups, du hast das Z ausgenommen, ok ^^
    Wobei ich so weit aber ehrlich gesagt gar nicht gedacht hatte, ich hatte das eher als kleineres Problemchen angesehen. Zumindest mir passiert es recht oft, dass ich den Bereich genau um 1 verbocke, weil ich nicht dran gedacht habe, ob nun was inklusive oder exklusiv ist, von daher hab ich das bei "Später" einsortiert.

    Dein Kommentar hab ich gesehen, wobei ich mir da eher die Frage gestellt hab, wie ich die Buchstaben so erweitern könnte, dass auch Zeichen und Zahlen inklusive sind.
    Und nachdem ich aus den 3 Bereichen KeyDown, KeyUp und KeyPress nicht schlau wurde, und dann auch noch beim schnellen Tippen eune "Durchmischung" der Farbe hatte, hab ich vorerst aufgegeben...

    Spawnie schrieb:

    KeyDown, KeyUp und KeyPress
    KeyDown kommt, wenn eine Taste gedrückt wurde. Da werden Tasten ausgewählt und Flags gesetzt.
    KeyPress reagiert auf AutoRepeat einer Taste.
    KeyUp stellt den Ausgangszustand wieder her.
    Bedenke, dass Text auch per C&P eingegeben werden kann, dies wird bei mir nicht berücksichtigt.
    Wenn Du weitere Zeichen berücksichtigen willst, pack alle in eine List(Of Keys) und frage dann, ob die aktuelle Taste Element dieser Liste ist (das ist ein Einzeiler).
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Also, der Code

    VB.NET-Quellcode

    1. Private Sub RichTextBox1_KeyDown(sender As Object, e As KeyEventArgs) Handles RichTextBox1.KeyDown
    2. RichTextBox1.SelectionColor = Color.Blue
    3. RichTextBox1.SelectionFont = New Font(RichTextBox1.Font, FontStyle.Regular)
    4. End Sub

    erfüllt den Wunsch nach einem farbigen Editieren zu 100% und klappt fast perfekt. Leider versteht er sich aber mit einem anderen Programmteil nicht.

    Meine Redo und Undo Buttons zicken ein wenig.

    VB.NET-Quellcode

    1. Private Sub Button1_Click_1(sender As Object, e As EventArgs) Handles FTUndo.Click
    2. If Me.RichTextBox1.CanUndo Then
    3. Me.RichTextBox1.Undo()
    4. End If
    5. End Sub
    6. Private Sub FTWdh_Click(sender As Object, e As EventArgs) Handles FTWdh.Click
    7. If Me.RichTextBox1.CanRedo Then
    8. Me.RichTextBox1.Redo()
    9. End If
    10. End Sub


    - Ich markiere Text1 & lösche ihn
    - Ich markiere Text2 & lösche ihn
    - Ich drücke "Undo" mehrfach als Test

    Und nun wird es merkwürdig. Klick 1 auf Undo bringt den gelöschten Text2 zurück, nur halt in blau. Klick 2 macht garnix (sichtbares). Klick 3 macht den Text2 wieder schwarz, Klick 4 holt Text 1 zurück in blau, Klick 5 macht nix (sichtbares), Klick 6 macht den Text1 schwarz.

    Vorher war es wirklich exakt wie es sein soll. 1 x Klick = 1 x rückgängig.

    Ich hab aber beim besten Willen keinen Schimmer wo dieses unsinnige Verhalten her kommt? Wieso 3 x klicken und diese komische Abfolge? Ich werd nicht schlau draus. ?(
    Sobald ich den oberen Part auskommentiere klappt die Undo/Redo Geschichte wieder perfekt... :/

    Habt ihr eine Idee?

    Spawnie schrieb:

    dass ich wirklich jede Taste in diese Liste packen müsste
    So isses.
    Bei dem UnDo(), ReDo(): Bei meinem KexDown-Code habe ich .SelectionLength auf 1 begrenzt. Füge mal diese Zeile bei Dir ein.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Spawnie schrieb:

    Wenn ich dafür aber eine Zeile markiere und per <-- löschen will verschwindet nur der erste Buchstabe
    Offensichtlich markierst Du nur diesen einen Buchstaben.
    Arbeite mal mit einer anderen Schriftfarbe, damit Du den Unterschied zwischen farbiger Schrift und markiertem Text besser sehen kannst.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Meine Standardfarbe ist ja schwarz, weil der Text ohne besondere Formatierung ankommt.
    Die Bearbeitungsfarbe ist blau:



    Das ist der Verlauf.
    1) Mein Ausgangstext

    2) Ich habe die ganze Zeile markiert

    3) Nachdem ich DELETE gedrückt habe ist das meine Ansicht...
    Bilder
    • Unbenannt.JPG

      29,87 kB, 189×420, 528 mal angesehen
    @Spawnie Klar.
    <- (Delete) löst selbstverständlich das .KeyDown-Event aus.
    Fange diese Taste ab:

    VB.NET-Quellcode

    1. If e.KeyCode <> Keys.Back Then
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    :D Das Thema will uns ärgern...

    Aaaaaaalso: Dein Tipp war richtig mit Delete ausnehmen. Wenn ich nun eine Zeile markiere und lösche und dann UNDO mache, passt es soweit.
    Dafür läuft nun aber was anderes unrund:
    • Ich kann nicht (oder habe keinen Weg gefunden) Text in vorhandenem Text ergänzen. Wenn ich mitten in eine vorhandene Zeil klicke und schreibe, wird der vorhandene Text überschrieben, statt nach hinten geschoben. Aus "AlterText" wird nun statt wie früher "AlterVorhandenerText" einfach "AlterVorhandener"
    • Ich habe die 3 x Klick auf Undo Problematik weg für gelöschte Passagen. Sie ist aber immer noch bei normalem Text vorhanden. Wenn ich z.B. 123 schreibe und dann Undo Klicke, dann muss ich jeweils 3 x Klicken um eine Zahl zu löschen. Ja ich weiß, ich kann die Delete Teste nehmen, aber ganz rund ist das ja trotzdem nicht an der Stelle.

    Spawnie schrieb:

    "AlterVorhandenerText" einfach "AlterVorhandener"
    Auch da ist ein Buchstabe selektiert, der durch den eingegebenen ersetzt wird. Beim Einfügen muss .SelectionLength = 0 sein.
    Mach Dir eine CheckBox Overwrite, mit der Du sdas steuerst.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!