none
How to change the color of text in a RichTextBox like that of Microsoft Word

    Question

  • I'm using a RichTextBox and would like to add a feature that allows the user to change text color on the fly by pressing color buttons located over the RichTextBox.  I want to be able to change the color of either highlighted text if there is any, or of text entered at the current caret position.  So far, I've written the following function which attempts to update my text color after after pressing any of the previously mentioned color buttons:

     

    private void UpdateTextColor()
    {
           // currentBrush is the Brush set with the color of the color button push (the color that the text is to be set to) and

           // rtb is my RichTextBox


           TextRange range = new TextRange(rtb.Selection.Start, rtb.Selection.End);

           if (rtb.Selection.IsEmpty)
           {
                  rtb.Selection.ApplyPropertyValue(TextElement.ForegroundProperty, currentBrush);
           }
           else
           {
                  range.ApplyPropertyValue(TextElement.ForegroundProperty, currentBrush);
           }
           rtb.Focus();
    }

     

    This kind of works; it changes the color of selected text properly, and changes the color of text entered from here on in if the caret is at the end of the end of the RichTextBox's document.  However, if before entering any text the color is changed (a color button is pressed), it doesn't change the color at the caret (any text entered is displayed in default black).  Also, if the caret is in the middle of a line (with no text selected) and the color is changed, the entire word's (every character in either direction up to the next period, comma, semicolor, line feed, space, etc) color is changed.  In such a situation where no text is selected I want to not change the color of existing text but only text entered from here on in.

     

    Any help would be much appreciated.

    Monday, November 05, 2007 9:10 AM

Answers

  • changing selection color is currently not supported.

     

    As for coloring the whole word when caret is in the middle of the word, this is by design. This is a result of spring loading - similar to the whole word becoming bold when you press ctrlB when the caret is in the m iddle of a word

     

    Tuesday, November 06, 2007 7:51 AM
  • fair enough.  i was able to get my RichTextBox color change functionality up to the same level as that of the WPF TextPad demo, with an example line of text above the RichTextBox changing color appropriately to the current color of the text at the RichTextBox's caret position.  having the whole word change color when the caret is in the middle of a word (with a selection lenght of 0) is something i can live with.  i kicked around adding in a new run consisting of only a space and setting its text to the new color, then deleting the space when text was typed in, but it was way to clunky and if the RichTextBox lost focus before any new text was entered the space remained.  anyways thanks for your help.

     

    Tuesday, November 06, 2007 8:46 AM

All replies

  • I'd suggest that you override the SelectionChanged event and determine what Brush you want to be in the foreground of the

    input text.

     

    The SelectionChange RoutedEvent also captures the text input because, when a character is inserted, the RichTextBox.Selection.Start Property change (the same happens with the TextBox.SelectionStart Property).

     

    I was having a similar issue with the Bruh in SelectedText Foreground and Background and I workaround it by making having a TextBox with a OpacityProperty set to 0 (zero) and a TextBlock behind it displaying the text as I wanted it to.

    I turned out to make separate TextRun with diferent Background and Foreground.

     

    Maybe you could do something in the same manner so, each time a diferent Brush was selected you'd add a run with the specified Foreground.

     

    Before this, when a new color is selected, you should create the Run and apply the Brush.

     

    In the correct order (in parentesis if a TextBox is used):

    -When new color is selected: Create a TextRange (Run with an index) and the intended properties;

    -When text is input, generate the FlowDocument joining the TextRanges (TextString add the Runs to the InlineCollection).

     

     

    Hope this help, even having some code to go until you get there.
    Monday, November 05, 2007 12:22 PM
  • Thanks Bigsby but I'm trying to keep all of the text in the same RichTextBox for saving / loading purposes; stacking a bunch of TextBoxes on top of each other doesn't seem like a good idea.  I'm working with the constantly creating new runs idea but its still full of small problems.  I can't seem to find a good workaround.

     

    Also you mentioned overridding the SelectionChanged event but is there really a need to do so; for what you're advising wouldn't just using the SelectionChanged event handler work fine?  Also I'm trying using a RichTextBox in my own user control and overridding the RichTextBox's events would require creating my own class which inherits from RichTextBox correct?  (I'm yet to override event handlers so not 100% sure of the process).

    Tuesday, November 06, 2007 4:21 AM
  • changing selection color is currently not supported.

     

    As for coloring the whole word when caret is in the middle of the word, this is by design. This is a result of spring loading - similar to the whole word becoming bold when you press ctrlB when the caret is in the m iddle of a word

     

    Tuesday, November 06, 2007 7:51 AM
  • fair enough.  i was able to get my RichTextBox color change functionality up to the same level as that of the WPF TextPad demo, with an example line of text above the RichTextBox changing color appropriately to the current color of the text at the RichTextBox's caret position.  having the whole word change color when the caret is in the middle of a word (with a selection lenght of 0) is something i can live with.  i kicked around adding in a new run consisting of only a space and setting its text to the new color, then deleting the space when text was typed in, but it was way to clunky and if the RichTextBox lost focus before any new text was entered the space remained.  anyways thanks for your help.

     

    Tuesday, November 06, 2007 8:46 AM