2

As the title suggests, my aim is to increment/decrement the font size of the current selection of text inside the RichTextBox.

This may seem trivial, and in fact it is - so long as the font size is the same for all text in the TextRange. When the selection contains text with different font sizes, the

range.GetPropertyValue(TextElement.FontSizeProperty);

which I use to get the previous value of the font size (necessary in order to know what to set the value to) returns DependencyProperty.UnsetValue .

Not only is this a problem, but also the fact that there isn't a method to increment the size, only one to explicitly set it to a given value is causing an issue here.

I've considered trying to parse the TextRange for sub ranges with different property values, but this seems like a really convoluted way to achieve something which should be trivial.

How do I go about this? Thanks in advance.

JessMcintosh
  • 460
  • 2
  • 6
  • 21

4 Answers4

1

I think any implementation, if it existed, would ultimately have to do the exact same thing you propose so your options are limited:

If your concern is that this is a lot of operations, you could be right about that and the only conceptual shortcut I can think of would be to apply a ScaleTransform. This of course is only going to make it appear to work and it isn't going to change the properties of the selection.

If your concern is that this is a lot of clutter in your user code, you are also right but I'd suggest hiding that by making your own RichTextBox and implementing the IncrementSizeOfSelection and DecrementSizeOfSelection yourself.

Mishax
  • 4,442
  • 5
  • 39
  • 63
1

I think this should work now... as I've commented in my last post, this takes care of the automatic merging of < run > elements when their textsize becomes same:

    private void sizeTextSel(int iVal)
    {
        TextSelection ts = _richTextBox.Selection;
        TextPointer tpStart = ts.Start;
        TextPointer tpEnd = ts.End;
        TextPointer tpRun = tpStart;

        int iSelLength = ts.Text.Length;
        int iStartRunLength;
        object fontSizeSelection;
        int iTotalSelected = 0, iSelect = 0,iNew=0;
        do
        {
            iStartRunLength = tpRun.GetTextRunLength(LogicalDirection.Forward);
            iSelect = iStartRunLength < iSelLength - iTotalSelected ? iStartRunLength : iSelLength - iTotalSelected;
            if (iStartRunLength > 0)
            {
                iSelect = iSelect == 0 ? 1 : iSelect;
                ts.Select(tpRun, tpRun.GetPositionAtOffset(iSelect, LogicalDirection.Forward));
                fontSizeSelection = ts.GetPropertyValue(TextElement.FontSizeProperty);
                if (fontSizeSelection != null)
                    ts.ApplyPropertyValue(TextElement.FontSizeProperty, (double)fontSizeSelection + iVal);
                iNew = tpRun.GetTextRunLength(LogicalDirection.Forward);
                if (iNew==0)
                    tpRun = tpRun.GetPositionAtOffset(iSelect + 1, LogicalDirection.Forward);
                else
                    tpRun = tpRun.GetPositionAtOffset(iSelect, LogicalDirection.Forward);
            }
            else
            {
                if (tpRun.Parent.GetType() == typeof(FlowDocument))
                    iSelect = 2;
                else
                    iSelect = 0;
                tpRun = tpRun.GetPositionAtOffset(1, LogicalDirection.Forward);
            }

            iTotalSelected += iSelect;

        } while (tpRun != null && iTotalSelected < iSelLength);

        ts.Select(tpStart, tpEnd);
    }
Stephan
  • 86
  • 5
0

Get the TextRange through RichTextBox's Selection which will give you TextRange, and you have a double value for your fontsize. Try this

 public void SetFontSizeForSelection(TextRange selection, double newFontSize)
        {
            if ((newFontSize - 0) < double.Epsilon)
                newFontSize = 1;
            selection.ApplyPropertyValue(TextElement.FontSizeProperty, newFontSize);
        }
123 456 789 0
  • 10,565
  • 4
  • 43
  • 72
  • Thanks the solution to setting a TextRange's font to a specific size, however this does not address the problem of having multiple font sizes within the TextRange. – JessMcintosh Sep 05 '13 at 09:06
  • What are you trying to achieve though? What do you mean by multiple font sizes – 123 456 789 0 Sep 05 '13 at 13:55
  • 1
    @Leo he means if we have "ABC" with A being 12pt, B being 10pt, and C being 8pt. That when you highlight "ABC" the font size for each letter increases by, say, 1pt. The result would then be A=13pt, B=11pt, C=9pt. – jamesSampica Sep 05 '13 at 14:15
  • Oh, okay. well. that's gonna be tricky. As far as I know, you can only get the entire selection as a TextRange object, and it's either you get the fontsize of the entire selection and set it but then you won't achieve what you want by increasing different font sizes on the selection of the RTB – 123 456 789 0 Sep 05 '13 at 14:24
0

I think the necessary operations are not too many. I've tried it with multiple different text sizes - this example only works when the selected text is enclosed in < RUN > elements. But it should be possible to extend the code for different elements like < span > Yet, I don't know how to handle something like < Paragraph >< Bold > Bolded < /Bold >< /Paragraph >

    private void sizeTextSel(int iVal)
    {
        TextSelection ts = _richTextBox.Selection;
        TextPointer tpStart = ts.Start;
        TextPointer tpEnd = ts.End;
        TextPointer tpRun = tpStart;

        int iSelLength = tpStart.GetOffsetToPosition(tpEnd);
        int iStartRunLength;
        object fontSizeSelection;
        int iTotalSelected = 0,iSelect;

        do
        {                   
            iStartRunLength = tpRun.GetTextRunLength(LogicalDirection.Forward);
            iSelect = iStartRunLength < iSelLength - iTotalSelected ? iStartRunLength : iSelLength - iTotalSelected;
            ts.Select(tpRun, tpRun.GetPositionAtOffset(iSelect,LogicalDirection.Forward));
            fontSizeSelection = ts.GetPropertyValue(TextElement.FontSizeProperty);
            if (fontSizeSelection != null)
                ts.ApplyPropertyValue(TextElement.FontSizeProperty, (double)fontSizeSelection + iVal);

            tpRun = tpRun.GetPositionAtOffset(iSelect + 1);
            while (tpRun != null && tpRun.Parent.GetType() != typeof(Run))
            {
                tpRun = tpRun.GetPositionAtOffset(1);
                //iOffset +=1;
            }
            iTotalSelected += iSelect+1;

        } while (tpRun != null && iTotalSelected < iSelLength);

        ts.Select(tpStart, tpEnd);
    }
Stephan
  • 86
  • 5
  • Well, this is not correct... I now realized, that when 'parsing' the text in the different < run> elements, the logic behind the rtb automatically merges these when the textsize becomes the same. For example: You have two < run > elements - the first has a text size of 10 the following has a textsize of 11. You have selected both and want to increase the textsize of both by 1. In the code you process the first < run > When finished the lenght of the < run > magically has changed and now has the size of both < run > elements. Not only that, the following run has a lenght of 0! Really confusing! – Stephan Sep 15 '15 at 22:30