Reputation: 460
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.
Upvotes: 2
Views: 2389
Reputation: 86
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);
}
Upvotes: 1
Reputation: 86
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);
}
Upvotes: 0
Reputation: 10865
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);
}
Upvotes: 0
Reputation: 4582
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.
Upvotes: 1