Why can't I change the color of repeated words in a RichTextBox?

二次信任 提交于 2020-02-03 09:57:31

问题


My program has to find specific words inside a RichTextBox and change their color (simple syntax highlighter). I am using Regex to find the words.
I'm able to find them all but if my text contains 2 or more of the same word, I can only change the color of the first one, the other ones get untouched.

Dim words As String = "(in|handles|object|sub|private|dim|as|then|if|regex)"
Dim rex As New Regex(words)
Dim mc As MatchCollection = rex.Matches(RichTextBox1.Text.ToLower)

Dim lower_case_text As String = RichTextBox1.Text.ToLower
For Each m As Match In mc
    For Each c As Capture In m.Captures
        MsgBox(c.Value)
        Dim index As Integer = lower_case_text.IndexOf(c.Value)
        Dim lenght As Integer = c.Value.Length

        RichTextBox1.Select(index, lenght)
        RichTextBox1.SelectionColor = Color.Blue
    Next
Next

My code needs to run from a button click. I think my problem is in the for each loop, but I'm not sure.
I already have a few versions of it, but none working.


回答1:


This method can be simplified using some RegexOptions

RegexOptions.Compiled Or RegexOptions.IgnoreCase

RegexOptions.Compiled:
Can be useful if the Text is long (faster execution at the expense of a slower startup).

RegexOptions.IgnoreCase
Performs a case-insensitive matching. You don't need to convert ToLower() the Text.

RegexOptions.CultureInvariant
Could be added when necessary.

See the Regular Expression Options document for more informations.
Also, see the Regex.Escape() method, if parts of the pattern could contain some metacharacters.

Your code can be reduced to:

Dim pattern As String = "in|handles|object|sub|private|dim|as|then|if|regex"
Dim regx As New Regex(pattern, RegexOptions.Compiled Or RegexOptions.IgnoreCase)
Dim matches As MatchCollection = regx.Matches(RichTextBox1.Text)

For Each match As Match In matches
    RichTextBox1.Select(match.Index, match.Length)
    RichTextBox1.SelectionColor = Color.Blue
Next



回答2:


I think that's because lower_case_text.IndexOf(c.Value) finds index only first match in string.

A quick hack would be to change lower_case_text every for cycle.

Like: "dim something dim something"

After finding first dim, replace it with something same length like "000"

So your lower_case_text will now be: "000 something dim something"

And then you will be able to get valid index of 2nd "dim"

It's not an elegant solution, but should work.

Hope it made seance.




回答3:


First, there's no need to use Captures collection (and also parenthesis) because Capture will hold same value as Match. Second, you can use inline regex options (for instance (?i) - set case-insensitive search) in the beginning of the regex pattern. The advantage of inline options is that you can set and cancel them in any part of your pattern (for instance (?-i) - cancel case-insensitive search).

Dim input = 
   "If i = 10 Then
        i = 0
    Else
        i = 5
    End If"
Dim pattern = "(?i)in|handles|object|sub|private|dim|as|then|else|end|if|regex"
Dim mc = Regex.Matches(input, pattern)
For Each m As Match In mc
    Dim index = m.Index
    Dim length = m.Length
Next


来源:https://stackoverflow.com/questions/53680544/why-cant-i-change-the-color-of-repeated-words-in-a-richtextbox

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!