0

Using WinForms, I have a RichTextBox which will hold the contents of a text file whose length will be limited only by what a RichTextBox can manage.

A section within it will be marked using a certain background color. I need to quickly identify where the section begins and ends. I don't trust that the section will be completely unbroken, and the marked area might cover the entire text--so I need to examine the background color of every character.

The obvious way to do this is to select each character in turn and get its SelectionBackColor:

  private TextRange? CalcMarkedTextRange() {

    var rtb = RichTextBox;
    var textLength = rtb.TextLength;

    // Store the range of whatever the user currently has selected

    var currentSelectionRange = new TextRange( rtb );

    rtb.Visible = false; // <--- To prevent slow screen updates

    // Find where the first and last color-marked characters are

    var markBegins = -1;
    var markEnds = -1;

    for ( int ix = 0; ix < textLength; ++ix ) {
      rtb.Select( ix, 1 );
      if ( rtb.SelectionBackColor == SelectedTextBackColor ) {
        if ( markBegins == -1 ) {
          markBegins = ix;
        }
        markEnds = ix;
      }
    }

    // Put back user's selection

    rtb.Select( currentSelectionRange );

    rtb.Visible = true;

    // See what we found

    if ( markBegins > -1 ) {
      // Return a single range encompassing all marked characters
      return new TextRange( markBegins, markEnds - markBegins + 1 );
    }

    return null;

  }

In the code above, TextRange is a structure that stores the start and length of a selection, just as you might expect.

If I don't hide the control by messing with its Visible property before scanning the colors, this code is unbelievably slow. You can see it scanning through, even with a relatively small amount of text. My test using about 4000 characters exhibited unacceptably poor performance.

I do hide it, it operates much more quickly, but there is still an ugly flash as the control disappears for a few seconds then comes back with its scroll position slightly off.

There must be a way to know the background color of an individual character without having to select it, though I imagine one would have to call a native Win32 method. But I have had no luck finding one.

Charles Jenkins
  • 340
  • 4
  • 10
  • https://stackoverflow.com/a/3282911/17034 – Hans Passant Jan 26 '23 at 23:26
  • I don't know if this will be faster, but you could use the [Text Object Model (TOM)](https://learn.microsoft.com/en-us/windows/win32/controls/text-object-model) to navigate the characters. There is a nice .Net Library ([TOM Classes for .NET](https://www.brad-smith.info/blog/projects/textobjectmodel) by Brad Smith) that makes this relatively painless and easier than the somewhat limited interfaces obtained by importing the native COM based TOM library. At least you would not be moving the RTB Selection and dealing with its screen updates. – TnTinMn Jan 28 '23 at 01:15

0 Answers0