Nur die aktive Zeile in einer RTB farblich hervorheben

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

Es gibt 22 Antworten in diesem Thema. Der letzte Beitrag () ist von max1605.

    Nur die aktive Zeile in einer RTB farblich hervorheben

    Hallo,

    ich stehe vor folgenden Problem:

    Ich habe in meinem Programm eine RTB, in welcher ich Text bearbeite, die teilweise mehrere Hundert Zeilen lang sind und den ganzen Bildschirm ausfüllen.

    Zur besseren Übersicht würde ich gerne die aktive Zeile (jene in welcher sich gerade der Cursor befindet) grau unterlegen und alle Textteile in dieser Zeile, die ein Datumsformat haben, gelb unterlegen (siehe Bild).
    Die Hervorhebungen sollen stets nur in der Zeile sein in der sich der Cursor befindet.

    Hat jemand eine Idee, wie ich das bewerkstelligen könnte?

    Vielen Dank im Voraus!
    Bilder
    • Markierte Zeile.png

      5,94 kB, 275×160, 1.123 mal angesehen
    die ein Datumsformat haben

    Dafür würde ich dir RegEx oder anders genannt Regular Expression empfehlen, würde hier im Forum schon oft behandelt, gibt sogar ein Tutorial dazu.
    die aktive Zeile

    Dabei wird dir helfen wenn du auf eine Richtextbox Umsteigst, und dort mit der .SelectionStart und der .BackColor arbeitest.
    Wenn ich nachher von der Arbeit wiederkomme kann ich gerne nochmals Beispiele Posten, wenn Bedarf besteht
    Hier habe ich Dir Code aus einem FUNKTIONIERENDEN Versuch:

    Quellcode

    1. Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
    2. Const EM_GETLINECOUNT = &HBA
    3. Const EM_LINELENGTH = &HC1
    4. Const EM_LINEINDEX = &HBB
    5. Const EM_LINEFROMCHAR = &HC9
    6. Const EM_GETLINE = &HC4
    7. Const EM_GETFIRSTVISIBLELINE = &HCE
    8. Const EM_CANUNDO = &HC6
    9. Const EM_UNDO = &HC7
    10. Const EM_EMPTYUNDOBUFFER = &HCD
    11. Sub MarkWholeLine(ByVal Ctrl As Object, Pos As Integer)
    12. Dim LG As Integer
    13. 'ST = ActLineStart(Ctrl)
    14. LG = LineLength(Ctrl, Pos)
    15. Ctrl.SelectionStart = LineStart(Ctrl, Pos)
    16. Ctrl.SelectionLength = LG
    17. End Sub
    18. Function LineText(Ctrl As Object)
    19. Return Ctrl.selectedtext
    20. End Function
    21. Function ActLineStart(ByVal Ctrl As Object)
    22. If TypeOf Ctrl Is TextBox Then
    23. Return LineStart(Ctrl, LineIndex(Ctrl, Ctrl.SelectionStart))
    24. Else
    25. Return LineStart(Ctrl, LineIndex(Ctrl, Ctrl.SelectionStart))
    26. End If
    27. End Function
    28. Function LineIndex(ByVal Ctrl As Object, ByVal CharPos As Integer)
    29. Dim hwnd As IntPtr = Ctrl.Handle
    30. Return SendMessage(Ctrl.Handle.ToInt32, EM_LINEFROMCHAR, CharPos, 0&)
    31. End Function
    32. Function LineStart(ByVal Ctrl As Object, ByVal Nr As Long)
    33. Return SendMessage(Ctrl.Handle.ToInt32, EM_LINEINDEX, Nr, 0&)
    34. End Function
    35. Function LineLength(ByVal Ctrl As Object, ByVal Nr As Integer)
    36. Dim LineChar As Short = LineStart(Ctrl, Nr) 'SendMessage(Ctrl.hWnd, EM_LINEINDEX, Nr, 0&)
    37. Dim LL As Integer = SendMessage(Ctrl.Handle.ToInt32, EM_LINELENGTH, LineChar, 0)
    38. Return LL
    39. End Function
    40. Private Sub RichTextBox1_MouseMove(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles RichTextBox1.MouseMove
    41. Dim POINT As System.Drawing.Point = New System.Drawing.Point()
    42. Dim Pos As Integer
    43. POINT.X = e.X
    44. POINT.Y = e.Y
    45. Pos = RichTextBox1.GetCharIndexFromPosition(POINT)
    46. Label1.Text = Pos.ToString
    47. Static LNr As Integer = -1
    48. If LineIndex(RichTextBox1, Pos) <> LNr Then
    49. LNr = LineIndex(RichTextBox1, Pos)
    50. MarkWholeLine(RichTextBox1, LNr)
    51. Label2.Text = LNr.ToString
    52. Label3.Text = LineText(RichTextBox1)
    53. End If
    54. End Sub


    Das löst sicher Deine Probleme.

    Viel Spaß!

    Horst
    @horstfh
    Ist ja voll nett von dir das du ihm zeigst wie du es gemacht hast, aber wäre es nicht besser wenn:
    Du ihm auch erklärst Wieso/Weshalb/Warum das ganze so umständlich sein muss.
    Und Ihm im gleichen Atemzug auchnoch zeigst wie man in dieses Wirrwarr die Datumserkennung einbaut?

    Denn so wie ich das sehe ist das nichts was nicht mit etwas RegEx und Standard RTB Methoden gelöst werden kann.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Gelöschter Benutzer“ ()

    So könnte man z.B. das Datum einfärben:

    VB.NET-Quellcode

    1. Sub colorText()
    2. Dim _Date As String = "(01.01.1999|31.12.2017)"
    3. Dim grex As New Regex(_Date)
    4. Dim _matchCol As MatchCollection = grex.Matches(RichTextBox1.Text)
    5. Dim StartCursorPosition As Integer = RichTextBox1.SelectionStart
    6. For Each m As Match In _matchCol
    7. Dim startIndex As Integer = m.Index
    8. Dim StopIndex As Integer = m.Length
    9. RichTextBox1.[Select](startIndex, StopIndex)
    10. RichTextBox1.SelectionBackColor = Color.Yellow
    11. RichTextBox1.SelectionStart = StartCursorPosition
    12. RichTextBox1.SelectionColor = Color.Black
    13. Next
    14. End Sub


    Bilder
    • RegEx.PNG

      9,07 kB, 274×115, 1.064 mal angesehen
    Kompliment!!!
    Habe nur das Problem, dass es bei mir (VS2010 und VS 2015) (noch) nicht funktioniert. Was könnte das verhindern? Imports System.Text.RegularExpressions
    natürlich gesetzt.


    Übrigens: Meinen Code bitte vergessen. Kritik war berechtigt.
    Für die Zeilenmarkierung schlage ich vor:

    Quellcode

    1. Private Sub RichTextBox1_MouseMove(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles RichTextBox1.MouseMove
    2. Dim POINT As System.Drawing.Point = New System.Drawing.Point()
    3. POINT.X = e.X
    4. POINT.Y = e.Y
    5. Dim CIx, Lg, LNr, St As Integer
    6. CIx = GetCharIndexFromPosition(RichTextBox1, POINT)
    7. LNr = GetLineIndexFromCharIndex(RichTextBox1, CIx)
    8. St = GetFirstCharIndexFromLine(RichTextBox1, LNr)
    9. Lg = GetFirstCharIndexFromLine(RichTextBox1, LNr + 1) - St
    10. MarkWholeLine(RichTextBox1, St, Lg)
    11. End Sub
    12. Sub MarkWholeLine(ByVal Ctrl As Object, St As Integer, Lg As Integer)
    13. Ctrl.SelectionStart = St
    14. Ctrl.SelectionLength = Lg
    15. End Sub
    16. Function GetCharIndexFromPosition(instance As TextBoxBase, Pt As Point) As Integer
    17. Return instance.GetCharIndexFromPosition(Pt)
    18. End Function
    19. Function GetLineIndexFromCharIndex(instance As TextBoxBase, Pos As Integer) As Integer
    20. Return instance.GetLineFromCharIndex(Pos)
    21. End Function
    22. Function GetFirstCharIndexFromLine(instance As TextBoxBase, lineNumber As Integer) As Integer
    23. Return instance.GetFirstCharIndexFromLine(lineNumber)
    24. End Function


    Ich habe das mit manuell gelb markierten Stellen ausprobiert. Klappt. Nur was ist mit der Datumsmarkierung?

    Gruß
    Horst
    Hier ist nochmal ein Versuch zur einfärbung von ausgewählten Linien.
    Es sei gewarnt, es werden Exception fliegen die mann noch abfangen muss und hier und da noch etwas verfeinert werden, aber es läuft fürs erste, evtl kann der @max1605 ja damit was anfangen.

    VB.NET-Quellcode

    1. Private Sub RichTextBox1_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs) Handles RichTextBox1.MouseDown
    2. Dim _rtbbox = DirectCast(sender, RichTextBox)
    3. Dim _index = _rtbbox.GetCharIndexFromPosition(e.Location)
    4. Dim _line = _rtbbox.GetLineFromCharIndex(_index)
    5. Dim _lineStart = _rtbbox.GetFirstCharIndexFromLine(_line)
    6. Dim _lineEnd = _rtbbox.GetFirstCharIndexFromLine(_line + 1) - 1
    7. _rtbbox.SelectionStart = _lineStart
    8. _rtbbox.SelectionLength = _lineEnd - _lineStart
    9. _rtbbox.SelectionColor = Color.White
    10. _rtbbox.SelectionBackColor = Color.DarkGray
    11. End Sub


    Edit:
    ​Nur was ist mit der Datumsmarkierung?

    Du ruft aber schon den Sub colorText() auf oder?
    Denn das ist bei mir VS2015 lauffähiger Code.
    Bilder
    • SelectionColor.PNG

      41,93 kB, 396×394, 133 mal angesehen
    Zunächst vielen herzlichen Dank für eure Mühe und die Vorschläge.
    Ich habe alle mal ausprobiert.

    Der Code von @horstfh aus Beitrag 3 markiert jeweils die Zeile, auf welcher sich die Maus befindet.
    Ich bräuchte allerdings nur eine farbliche Hervorhebung (SelectionColor) (innerhalb welcher ich dann selbst einen Teil markieren und bspw. löschen kann).
    Zudem navigiere ich in meiner RTB zu 99% mit den Pfeiltasten, sodass die farbliche Hervorhebung stets da sein müsste, wo ich den Cursor (den blinkenden Balken) gerade mit den Pfeiltasten hinnavigiert habe.

    Ich habe mich bemüht den Code zu verstehen und anzupassen, aber leider habe ich es nicht hinbekommen den Code so umzustellen, dass er auf die Navigation mit den Pfeiltasten reagiert und das er statt des markieren der Zeile, diese nur farblich hervorhebt.
    Hat da vielleicht einer eine Idee?

    Der Code von @Kameo aus Beitrag 6 färbt die Datumsangaben 01.01.1999 und 31.12.2017 in der RTB gelb ein.
    Wenn das mit dem Hervorheben der Zeile in Grau klappt, dann würde ich gerne versuchen (vielleicht auch mit eurer freundlichen Hilfe) diesen Code in die "Hervorhebungsprozedur" irgendwie einzubinden und so zu erweitern, dass er alle möglichen Datumsangaben erkennt.

    Den Code von @horstfh aus Beitrag 7 habe ich leider nicht zum laufen bekommen.
    In Zeile 15

    VB.NET-Quellcode

    1. Ctrl.SelectionLength = Lg
    wird das "Lg" rot unterstrichen und folgende Fehlermeldung erscheint:

    Ein Ausnahmefehler des Typs "System.ArgumentOutOfRangeException" ist in Microsoft.VisualBasic.dll aufgetreten.
    Zusätzliche Informationen: InvalidArgument=Value mit dem Wert -1 ist für SelectionLength ungültig.

    Somit konnte ich den Code leider nicht ausprobieren.

    Der Code von @Kameo aus Beitrag 8 hebt die Zeile die ich anklicke grau hervor, so wie ich mir das vorgestellt habe.
    Auch hier habe ich vergeblich versucht den Code so umzustellen, dass er auf die Navigation mit den Pfeiltasten reagiert.
    Des Weiteren fällt mir nichts ein, was ich tun könnte, dass sich die Hervorhebung wieder aufhebt, wenn ich die Zeile mit dem Cursor wieder verlasse (so das stets nur eine einzige Zeile hervorgehoben ist).

    Zudem erhalte ich irgendwann immer in Zeile 8

    VB.NET-Quellcode

    1. _rtbbox.SelectionLength = _lineEnd - _lineStart
    folgende Fehlermeldung:

    Ein Ausnahmefehler des Typs "System.ArgumentOutOfRangeException" ist in System.Windows.Forms.dll aufgetreten.
    Zusätzliche Informationen: InvalidArgument=Value mit dem Wert -41 ist für SelectionLength ungültig.

    Ich würde mich freuen und wäre sehr dankbar, wenn wer Lust hätte, mir da weiterzuhelfen!
    Erstmal super das du dir die Codes zu Herzen genommen hast!
    Mir ist klar das mein Code nicht 1:1 auf dein Problem anwendbar ist, aber das war auch nicht das Ziel.
    Mir ist es wichtig das man den Code verstehe und auch gerne mit uns im Forum erarbeitet.
    Also nun zu deinem Problem:
    Ein Ausnahmefehler des Typs "System.ArgumentOutOfRangeException" ist in System.Windows.Forms.dll aufgetreten.

    Ich hoffe du weißt warum die Exception her fliegt?
    Hier muss du natürlich abfragen, was passiert wenn dein Text Irgendwann Mal zuende ist, denn dann lässt sich nicht mehr mit _lineEnd - _lineStart rechnen
    Navigation mit den Pfeiltasten reagiert.

    Da werde ich mich selbst heute nach der Arbeit nochmals schlau machen.
    Des Weiteren fällt mir nichts ein, was ich tun könnte, dass sich die Hervorhebung wieder aufhebt

    Dazu hätte ich zwei Vorschläge, entweder gehst du bei jeder Zeilenänderung den kompletten Text durch und setzt dann doch die .BackColor / .SelectionColor -> Unperformant.
    Der Zweite Vorschlag wäre, du merkst dir irgendwo .SelectionLength inkl. . SelectionStart und setzt diese bei einem Linienwechsel wieder auf Weiß.
    Evtl. sind das ja ein paar Schlagwörter mit den du etwas anfangen kannst.
    Danke @Kameo
    Ich habe ein bisschen am Code gebastelt und bin nun soweit gekommen, dass tatsächlich nur die Zeile hervorgehoben wird, die angeklickt wird.
    (Wird nun eine Zeile angeklickt, dann wird diese grau hervorgehoben und die Hervorhebung der vorherigen Zeile erlischt).

    Der Code sieht nun wie folgt aus:

    VB.NET-Quellcode

    1. Public Class Form1
    2. Public lineStartV, lineEndV As Integer
    3. Private Sub RichTextBox1_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs) Handles RichTextBox1.MouseDown
    4. Dim _rtbbox = DirectCast(sender, RichTextBox)
    5. Dim _index = _rtbbox.GetCharIndexFromPosition(e.Location)
    6. Dim _line = _rtbbox.GetLineFromCharIndex(_index)
    7. Dim _lineStart = _rtbbox.GetFirstCharIndexFromLine(_line)
    8. Dim _lineEnd = _rtbbox.GetFirstCharIndexFromLine(_line + 1) - 1
    9. If lineStartV = 0 Then
    10. _rtbbox.SelectionStart = _lineStart
    11. _rtbbox.SelectionLength = _lineEnd - _lineStart
    12. lineStartV = _lineStart
    13. lineEndV = _lineEnd
    14. _rtbbox.SelectionColor = Color.White
    15. _rtbbox.SelectionBackColor = Color.DarkGray
    16. _rtbbox.SelectionStart = _lineStart
    17. _rtbbox.SelectionLength = 0
    18. Else
    19. _rtbbox.SelectionStart = _lineStart
    20. _rtbbox.SelectionLength = _lineEnd - _lineStart
    21. _rtbbox.SelectionColor = Color.White
    22. _rtbbox.SelectionBackColor = Color.DarkGray
    23. _rtbbox.SelectionStart = lineStartV
    24. _rtbbox.SelectionLength = lineEndV - lineStartV
    25. _rtbbox.SelectionColor = Color.Black
    26. _rtbbox.SelectionBackColor = Color.White
    27. lineStartV = _lineStart
    28. lineEndV = _lineEnd
    29. _rtbbox.SelectionStart = _lineStart
    30. _rtbbox.SelectionLength = 0
    31. End If
    32. End Sub
    33. End Class


    Allerdings habe ich noch folgende Probleme:
    1. Wenn die erste Zeile ein mal hervorgehoben wird, dann bleibt diese immer hervorgehoben.
    Die Hervorhebung verschwindet nicht, wie bei den anderen Zeilen.

    2. Ich komme mit dem Ausnahmefehler beim anklicken der letzten Zeile leider nicht zurecht.
    (Ich weiß leider nicht, wie ich ihn beseitigen kann.)

    3. Ich bin immer noch am Überlegen, wie ich in der hervorgehobenen Zeile ein Datum in gelb hervorheben kann.

    4. Ich suche immer noch nach einer Möglichkeit, dass der Code auf die Navigation mit Pfeiltasten reagiert.
    Wenn ich den Code in ein KeyDown oder KeyPress Event der RTB packe, dann kommt das Problem, dass er "e.Location" nicht erkennt

    max1605 schrieb:

    Allerdings habe ich noch folgende Probleme:
    1. Wenn die erste Zeile ein mal hervorgehoben wird, dann bleibt diese immer hervorgehoben.
    Die Hervorhebung verschwindet nicht, wie bei den anderen Zeilen.

    2. Ich komme mit dem Ausnahmefehler beim anklicken der letzten Zeile leider nicht zurecht.
    (Ich weiß leider nicht, wie ich ihn beseitigen kann.)

    3. Ich bin immer noch am Überlegen, wie ich in der hervorgehobenen Zeile ein Datum in gelb hervorheben kann.

    4. Ich suche immer noch nach einer Möglichkeit, dass der Code auf die Navigation mit Pfeiltasten reagiert.
    Wenn ich den Code in ein KeyDown oder KeyPress Event der RTB packe, dann kommt das Problem, dass er "e.Location" nicht erkennt


    Punkt 2 tritt bei mir nicht auf. Versuche doch mal, mit dem Textende zu experimentieren (Leerzeilen anhängen oder entfernen)

    Punkt 3 kann ich mir die Lösung so vorstellen: Die Farben der Einzelzeichen der Zeile prüfen und entsprechend einzeln zu ändern.


    Punkt 4
    Dazu habe ich Deinen Code gesplittet:

    Quellcode

    1. Private Sub RichTextBox1_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs) Handles RichTextBox1.MouseDown
    2. Dim _rtbbox = DirectCast(sender, RichTextBox)
    3. Dim _index = _rtbbox.GetCharIndexFromPosition(e.Location)
    4. Dim _line = _rtbbox.GetLineFromCharIndex(_index)
    5. Zeilemarkieren(_rtbbox, _line) ' eingefügt
    6. End Sub

    Und die restlichen Zeilen in die Sub ZeileMarkieren. Und die rufst Du auf aus

    Quellcode

    1. Private Sub RichTextBox1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles RichTextBox1.KeyDown
    2. Dim _line As Integer = RichTextBox1.GetLineFromCharIndex(RichTextBox1.SelectionStart)
    3. Zeilemarkieren(RichTextBox1, _line)
    4. End Sub

    Das ist noch nicht optimal aber wohl der Ansatz.

    An Punkt 1 bin ich noch.
    Gruß
    Horst

    PS: Punk1:
    Deine Zeile

    Quellcode

    1. If lineStartV = 0 Then

    ist das Problem
    Setze zu Anfang den Wert auf -1 und ändere die Abfrage entsprechen.

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

    3. Ich bin immer noch am Überlegen, wie ich in der hervorgehobenen Zeile ein Datum in gelb hervorheben kann.


    Spoiler anzeigen

    VB.NET-Quellcode

    1. Sub colorText()
    2. Dim _Date As String = "(01.01.1999|31.12.2017)"
    3. Dim grex As New Regex(_Date)
    4. Dim _matchCol As MatchCollection = grex.Matches(RichTextBox1.Text)
    5. Dim StartCursorPosition As Integer = RichTextBox1.SelectionStart
    6. For Each m As Match In _matchCol
    7. Dim startIndex As Integer = m.Index
    8. Dim StopIndex As Integer = m.Length
    9. RichTextBox1.[Select](startIndex, StopIndex)
    10. RichTextBox1.SelectionBackColor = Color.Yellow
    11. RichTextBox1.SelectionStart = StartCursorPosition
    12. RichTextBox1.SelectionColor = Color.Black
    13. Next
    14. End Sub


    Hierfür kannst du den Code hier fast 1:1 verwenden, was du abändern müsstest ist folgendes:
    Du müsstest dir für RegEx ein Pattern erstellen was nach einem Datumsformat sucht, sprich XX.XX.XXXX wobei X für eine Beliebige Zahl zwischen 0-9 stehen kann.
    Desweitern musst du Dim startIndex As Integer = m.Index & Dim StopIndex As Integer = m.Length auf deine Aktuell aktive Zeile begrenzen.
    Begrenzt du dein RegEx Pattern nicht auf die aktive Zeile wird natürlich jedes Datum in deinem Text gelb.
    Hallo Max1605
    vielen Dank für diese interessante Aufgabe. Die Diskussion war sehr anregend.
    Danke an Kameo für den Lösungsansatz mit regex. Davon hatte ich nur geringes Wissen. Jetzt kann ich aber an Max den Tipp geben: Statt der festen Datumswerte kannst Du folgende Lösung verwenden:

    Quellcode

    1. Dim _Date As String = "\d+\.\d+\.\d{4}|\d+\/\d+\/\d{4}"


    Dann werden auch Werte mit einer Tages- oder Monatsziffer sowie in englicher Schreibweise erkannt.

    Euch Beiden alles Gute!
    Bis die Tage!
    Horst
    Hallo,

    @horstfh und @Kameo ich melde mich mal mit einem Zwischenbericht.

    Punkt 1 ist erledigt. Wert auf -1 gesetzt und es funktioniert. Dankeschön!

    In den letzten Tagen habe ich für das Markieren des Datums auch noch eine Lösung gefunden (Punkt 3). Allerdings eine weniger saubere Lösung.
    Mir ist aufgefallen, dass in meinen Texte vor und nach dem Datum immer dasselbe steht. Daher kam ich auf die Idee, dass in der aktiven Zeile nach diesen beiden Elementen vor und nach dem Datum gesucht wird, und dann der Bereich dazwischen markiert wird.
    Mein Code sieht nun wie Folgt aus:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Text.RegularExpressions
    2. Public Class Form1
    3. Public lineStartV, lineEndV As Integer
    4. Private Sub RichTextBox1_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs) Handles RichTextBox1.MouseDown
    5. Dim _rtbbox = DirectCast(sender, RichTextBox)
    6. Dim _index = _rtbbox.GetCharIndexFromPosition(e.Location)
    7. Dim _line = _rtbbox.GetLineFromCharIndex(_index)
    8. Dim _lineStart = _rtbbox.GetFirstCharIndexFromLine(_line)
    9. Dim _lineEnd = _rtbbox.GetFirstCharIndexFromLine(_line + 1) - 1
    10. Dim von As String = " v. "
    11. Dim zu As String = ", "
    12. Dim options As RichTextBoxFinds
    13. If lineStartV = -1 Then
    14. _rtbbox.SelectionStart = _lineStart
    15. _rtbbox.SelectionLength = _lineEnd - _lineStart
    16. lineStartV = _lineStart
    17. lineEndV = _lineEnd
    18. _rtbbox.SelectionColor = Color.White
    19. _rtbbox.SelectionBackColor = Color.DarkGray
    20. If _rtbbox.SelectedText.Contains(von) And _rtbbox.SelectedText.Contains(zu) Then
    21. _rtbbox.SelectionStart = _rtbbox.Find(von, _lineStart, _lineEnd, options)
    22. _rtbbox.SelectionLength = _rtbbox.Find(zu, _lineStart, _lineEnd, options) - _rtbbox.Find(von, _lineStart, _lineEnd, options)
    23. _rtbbox.SelectionBackColor = Color.Yellow
    24. _rtbbox.SelectionColor = Color.Black
    25. Else
    26. End If
    27. _rtbbox.SelectionStart = _lineStart
    28. _rtbbox.SelectionLength = 0
    29. Else
    30. _rtbbox.SelectionStart = _lineStart
    31. _rtbbox.SelectionLength = _lineEnd - _lineStart
    32. _rtbbox.SelectionColor = Color.White
    33. _rtbbox.SelectionBackColor = Color.DarkGray
    34. If _rtbbox.SelectedText.Contains(von) And _rtbbox.SelectedText.Contains(zu) Then
    35. _rtbbox.SelectionStart = _rtbbox.Find(von, _lineStart, _lineEnd, options)
    36. _rtbbox.SelectionLength = _rtbbox.Find(zu, _lineStart, _lineEnd, options) - _rtbbox.Find(von, _lineStart, _lineEnd, options)
    37. _rtbbox.SelectionBackColor = Color.Yellow
    38. _rtbbox.SelectionColor = Color.Black
    39. Else
    40. End If
    41. _rtbbox.SelectionStart = lineStartV
    42. _rtbbox.SelectionLength = lineEndV - lineStartV
    43. _rtbbox.SelectionColor = Color.Black
    44. _rtbbox.SelectionBackColor = Color.White
    45. lineStartV = _lineStart
    46. lineEndV = _lineEnd
    47. _rtbbox.SelectionStart = _lineStart
    48. _rtbbox.SelectionLength = 0
    49. End If
    50. End Sub
    51. End Class

    Allerdings werden hierbei die ersten 4 Zeichen vor dem Datum zu viel in gelb markiert (siehe Bild).
    Ich bin die ganze Zeit am Überlegen, wie ich das ändern kann, aber habe noch keine Lösung gefunden.
    Die Regex Methode von euch werde ich aber auch noch ausprobieren. Diese Lösung scheint mir deutlich sauberer als meine.

    Bei Punkt 2 bin ich leider noch nicht weitergekommen. Ich würde nur ungern zusätzliche Zeilen an den Text ranhängen.

    Bei Punkt 4 gelingt mir leider das Splitten vom Code nicht :S
    Bilder
    • Markiertes Datum.PNG

      2,94 kB, 266×216, 120 mal angesehen
    Moin @max1605
    hierbei die ersten 4 Zeichen vor dem Datum zu viel in gelb markiert

    Wenn du auf Meine RegEx Methode mit @horstfh RegEx Pattern umsteigst hast du das Problem nicht mehr (siehe Bild.)
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Sub colorText()
    2. Dim _Date As String = "\d+\.\d+\.\d{4}|\d+\/\d+\/\d{4}"
    3. Dim grex As New Regex(_Date)
    4. Dim _matchCol As MatchCollection = grex.Matches(Me._rtbbox.Text)
    5. Dim StartCursorPosition As Integer = Me._rtbbox.SelectionStart
    6. For Each m As Match In _matchCol
    7. Dim startIndex As Integer = m.Index
    8. Dim StopIndex As Integer = m.Length
    9. Me._rtbbox.[Select](startIndex, StopIndex)
    10. Me._rtbbox.SelectionBackColor = Color.Yellow
    11. Me._rtbbox.SelectionStart = StartCursorPosition
    12. Me._rtbbox.SelectionColor = Color.Black
    13. Next
    14. End Sub



    2. Ich komme mit dem Ausnahmefehler beim anklicken der letzten Zeile leider nicht zurecht.

    Das sieht leider danach aus, das wir hier um ein UserControl was von RichTextBox erbt nicht herumkommen, den die standard RTB gibt, soweit ich das sehe, diese Funktion nicht her. Ich lasse mich da gerne eines besseren belehren.

    @horstfh
    Zeilemarkieren(RichTextBox1, _line) wo ziehst du das den her?

    Um deine Zeile per Arrowkeys (Up/Down) zu markieren, müsstest du so vorgehen:

    VB.NET-Quellcode

    1. ​Private Sub RichTextBox1_KeyDown(sender As Object, e As KeyEventArgs) Handles _rtbbox.KeyDown
    2. Select Case e.KeyCode
    3. Case Keys.Up, Keys.Down
    4. colorText()
    5. End Select
    6. End Sub

    Wichtig dabei ist das du vorher die Aktuelle Zeile mit übergibst
    Bilder
    • RegEx.PNG

      2,99 kB, 155×151, 898 mal angesehen
    Problem 3 Lösung mit colorText von Kameo

    Für Problem 2 und 4 habe ich es so gelöst:

    Spoiler anzeigen
    Private _line As Integer = -1
    Private Sub RTF1_Mousedown(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles RTF1.MouseDown
    Dim _rtbbox = DirectCast(sender, RichTextBox)
    Dim _index = _rtbbox.GetCharIndexFromPosition(e.Location)

    If _line > -1 Then
    ZeileDemarkieren(RTF1, _line)
    End If

    _line = _rtbbox.GetLineFromCharIndex(_index)
    Zeilemarkieren(_rtbbox, _line) ' eingefügt

    End Sub

    Private Sub RichTextBox1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles RTF1.KeyDown
    Dim St As Integer = RTF1.SelectionStart

    If _line > -1 Then
    ZeileDemarkieren(RTF1)
    End If
    _line = RTF1.GetLineFromCharIndex(St)
    Zeilemarkieren(RTF1)
    End Sub

    Sub Zeilemarkieren(_rtbBox As RichTextBox)
    Dim _lineStart = _rtbBox.GetFirstCharIndexFromLine(_line)
    Dim _lineEnd = _rtbBox.GetFirstCharIndexFromLine(_line + 1) - 1

    'If linestartv = 0 Then
    If _lineEnd > _lineStart Then
    _rtbBox.SelectionStart = _lineStart
    _rtbBox.SelectionLength = _lineEnd - _lineStart

    'linestartv = _lineStart
    'lineendv = _lineEnd

    _rtbBox.SelectionColor = Color.White
    _rtbBox.SelectionBackColor = Color.DarkGray

    _rtbBox.SelectionStart = _lineStart
    _rtbBox.SelectionLength = 0
    End If

    End Sub

    Sub ZeileDemarkieren(_rtbBox As RichTextBox)
    Dim _lineStart = _rtbBox.GetFirstCharIndexFromLine(_line)
    Dim _lineEnd = _rtbBox.GetFirstCharIndexFromLine(_line + 1) - 1

    'If linestartv = 0 Then
    If _lineEnd > _lineStart Then
    _rtbBox.SelectionStart = _lineStart
    _rtbBox.SelectionLength = _lineEnd - _lineStart

    'linestartv = _lineStart
    'lineendv = _lineEnd

    _rtbBox.SelectionColor = Color.Black
    _rtbBox.SelectionBackColor = Color.White

    _rtbBox.SelectionStart = _lineStart
    _rtbBox.SelectionLength = 0
    End If

    End Sub


    Gruß
    Horst
    So, ich habe den Code mal zusammengebastelt (siehe unten) und jetzt läuft alles fast richtig.
    Habe auch noch die Funktion ergänzt, dass die Markierugen verschwinden, wenn "Enter" gedrückt wird.
    Vielen Dank für eure Hilfe @horstfh und @Kameo !

    Das einzige was nicht funktioniert ist folgendes:
    Wenn ich mit der Maus eine Zeile anklicke, dann wird diese Markiert.
    Wenn ich aber mit den Arrowkeys navigiere, dann wird beim Drücken jeweils die vorherige Zeile markiert.
    Sprich, wenn ich Arrowkey-Down drücke, dann wird die dadrüberliegende Zeile markiert, also jene die eben (vor dem Tastendruck) noch die aktive war.
    Bei Arrowkey-Up passiert das selbe, logischweise aber umgekehrt.

    Code:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Text.RegularExpressions
    2. Public Class Form1
    3. Private _line As Integer = -1
    4. Public MarkVorh As Boolean = False
    5. Private Sub RTF1_Mousedown(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles RichTextBox1.MouseDown
    6. Dim _rtbbox = DirectCast(sender, RichTextBox)
    7. Dim _index = _rtbbox.GetCharIndexFromPosition(e.Location)
    8. If _line > -1 Then
    9. ZeileDemarkieren(RichTextBox1, _line)
    10. End If
    11. _line = _rtbbox.GetLineFromCharIndex(_index)
    12. Zeilemarkieren(_rtbbox, _line)
    13. End Sub
    14. Private Sub RichTextBox1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles RichTextBox1.KeyDown
    15. Select Case e.KeyCode
    16. Case Keys.Up, Keys.Down
    17. Dim St As Integer = RichTextBox1.SelectionStart
    18. If _line > -1 Then
    19. ZeileDemarkieren(RichTextBox1, _line)
    20. End If
    21. _line = RichTextBox1.GetLineFromCharIndex(St)
    22. Zeilemarkieren(RichTextBox1, _line)
    23. Case Keys.Enter
    24. If MarkVorh = True Then
    25. ZeileDemarkieren(RichTextBox1, _line)
    26. MarkVorh = False
    27. End If
    28. End Select
    29. End Sub
    30. Sub Zeilemarkieren(_rtbBox As RichTextBox, _line As Integer)
    31. Dim _lineStart = _rtbBox.GetFirstCharIndexFromLine(_line)
    32. Dim _lineEnd = _rtbBox.GetFirstCharIndexFromLine(_line + 1) - 1
    33. If _lineEnd > _lineStart Then
    34. _rtbBox.SelectionStart = _lineStart
    35. _rtbBox.SelectionLength = _lineEnd - _lineStart
    36. _rtbBox.SelectionColor = Color.White
    37. _rtbBox.SelectionBackColor = Color.DarkGray
    38. ColorDate(RichTextBox1)
    39. _rtbBox.SelectionStart = _lineStart
    40. _rtbBox.SelectionLength = 0
    41. End If
    42. MarkVorh = True
    43. End Sub
    44. Sub ZeileDemarkieren(_rtbBox As RichTextBox, _line As Integer)
    45. Dim _lineStart = _rtbBox.GetFirstCharIndexFromLine(_line)
    46. Dim _lineEnd = _rtbBox.GetFirstCharIndexFromLine(_line + 1) - 1
    47. If _lineEnd > _lineStart Then
    48. _rtbBox.SelectionStart = _lineStart
    49. _rtbBox.SelectionLength = _lineEnd - _lineStart
    50. _rtbBox.SelectionColor = Color.Black
    51. _rtbBox.SelectionBackColor = Color.White
    52. _rtbBox.SelectionStart = _lineStart
    53. _rtbBox.SelectionLength = 0
    54. End If
    55. End Sub
    56. Sub ColorDate(_rtbbox As RichTextBox)
    57. Dim _Date As String = "\d+\.\d+\.\d{4}|\d+\/\d+\/\d{4}"
    58. Dim grex As New Regex(_Date)
    59. Dim _matchCol As MatchCollection = grex.Matches(_rtbbox.SelectedText)
    60. Dim StartCursorPosition As Integer = _rtbbox.SelectionStart
    61. For Each m As Match In _matchCol
    62. Dim startIndex As Integer = m.Index
    63. Dim StopIndex As Integer = m.Length
    64. _rtbbox.[Select](startIndex, StopIndex)
    65. _rtbbox.SelectionStart = StartCursorPosition + startIndex
    66. _rtbbox.SelectionBackColor = Color.Yellow
    67. _rtbbox.SelectionColor = Color.Black
    68. Next
    69. End Sub
    70. End Class
    Eine Korrektur!

    In ZeileDeMarkieren fehlt in Zeile 72
    ColorDate(...)

    Sonst ok.

    Für das Problem mit der nachhinkenden Markierung bei KeyDown habe ich auch keine Idee.
    Anscheinend wird das KeyDown-Ereignis erst gemeldet, wenn der ganze Vorgang abgeschlossen UND der Zeilenwechsel (bei den Pfeitasten) ausgeführt ist.

    Das war's für mich!

    Macht es gut!
    Herzliche Grüße
    Horst


    ~blaze~: Rot ist den Moderatoren vorbehalten

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