RichTextBox SelectionFont is unexpectedly *not* null - winforms

I'd like to change the font size of a chunk of RTF without erasing the bold / italic / underline formatting (an issue similar to the one in this question). The accepted answer is to modify the selection of the text box until the SelectionFont propery is null in order to find runs of consistently formatted text which can be modified individually. Sounds reasonable. However the actual behavior of the RichTextBox control seems to be inconsistent with the documentation.
In the documentation for RichTextBox.SelectionFont MSDN states:
If the current text selection has more than one font specified, this
property is null.
However, this code which uses mixed bold / regular text doesn't behave as you'd expect:
var rtb = new RichTextBox {
Rtf = #"{\rtf1 This is \b bold\b0.}"
};
rtb.SelectAll();
// Now you'd expect rtb.SelectionFont to be null,
// but it actually returns a Font object
Is there any other reliable way of formatting the text so that I can change the font size without clobbering the other formatting. (Manipulating the RTF directly is OK, I'm not absolutely set on using WinForms to achieve this).

I've given up on trying to go through Winforms to fix this. As I'm applying the change to a whole document (rather than just one portion), it turns out that it's not too hard to modify the RTF directly.
In this case I'm interested in the font size, which is represented by the \fs command. So to replace all the 8.5pt text with 10pt text, you can replace \fs17 with \fs20. (Yes, RTF font sizes come in units of half a point, apparently).
This seems to work well enough, although it does feel like one of those "let's mangle our HTML using regular expressions" type solutions, so I'm not convinced that it's very robust.

Take a look at this:
Changing font for richtextbox without losing formatting
I think it's the same issue. LarsTech's solution is working perfectly for me.

Related

ToolTip works very slow for long text (2000+ chars)

We need to use the built-in WinForms tooltip control to display a very long tooltip (about 4000 characters) for one of our controls. But if we do so, the form freezes for a minute or two when we place the mouse pointer into the target control to see the tip. And nothing happens after that.
We experimented and detected that the standard tooltip starts to work very slow when it has about 2000 chars, and the situation becomes much worse when we increase the number of chars. Is it a known issue, and is there any workaround for it? Please, don't suggest to trim the tip text - we need to display the string as is.
When you assign a string of text to a ToolTip, part of the process of drawing it involves calls to USP10.dll which handles Unicode layout of characters on screen. I was able to see this by looking at the stack trace while the program was freezing. The performance of this layout is terrible for long strings.
Disabling Visual Styles for the application (commenting out EnableVisualStyles()) fixed the problem - the tooltip displays immediately, though this is not an optimal solution.
I kept looking and found this page which indicates the problem may be linked to layout of long strings where word-wrap is necessary. By inserting line breaks into the tooltip text, I found that the string displayed immediately. So, if you can determine where to insert the line breaks manually, the ToolTip should display quickly.
What about using another Tooltip , i.e. HtmlToolip?

Line spacing for different FontSizes in WPF RichtextBox

I want my RichtextBox to enable line spacing chosen by user (multiplier of 1, 1.5 or 2). I tried to programatically change LineHeight of paragraphs, setting it to FontSize*multiplier. That works fine, but it can't be used for different fontSizes in the same paragraph, because then I have to choose one of the sizes for the calculation of LineHeight.
I would like to have it similar like in WordPad or OpenOffice, where the actual LineHeight is calculated for each line using the biggest fontSize used on the line.
Is there any possibility to change the LineHeight for lines or to tell the RichTextBox to just use the multiplier? Or any other solution?
I think you are looking for the LineStackingStrategy="MaxHeight" for the Blocks. See this page: http://msdn.microsoft.com/en-us/library/system.windows.documents.block.linestackingstrategy.aspx

TextBlock inside a Viewbox - strange rendering

This is a question regarding a very simple construction - I have the following XAML:
<Viewbox Height="100" Stretch="Uniform">
<TextBlock FontFamily="Georgia">My Cool Text</TextBlock>
</Viewbox>
This is quite simple to understand. Yet when I start the program I get strange blurry text (there are no bitmap effects anywhere in my project).
(left side - the designer view in VS2010, right side - the running application)
Does anyone have ANY suggestions about why this is happening??
While Jefim has correctly answered his own question, I wanted to explain why you get this behaviour when using this particular set of features. Jefim suggests that this is a bug in WPF, but it's not. The problem arises as a result of asking for WPF to do something impossible. It has to pick a compromise when you've asked for this impossible thing, and the result is what you see above.
The explanation is a bit long for a comment, which is why I'm putting it in a separate answer.
This example uses two mutually contradictory features of WPF. Those features are:
The ability to render visuals consistently at any scale
The ability to render text in the same way GDI32 renders text
You can't use both features at once. GDI32 renders text in a way that cannot be scaled consistently: if a particular piece of text at a certain font size happens to be 200 pixels wide, if you multiply the font size by 3, and render the same text in the same font family at that new font size, in GDI32 it probably won't be 600 pixels - it'll be close, but it will typically not be quite right.
GDI32 messes with the shapes and widths of characters in order to enhance the clarity and sharpness of the text. Specifically, it bends letters out of shape so that their features align better with the pixels on your screen. And where necessary, it will adjust the width of individual characters to be an exact number of pixels wide. Since this letter bending is all based around actual pixels, it bends text in different ways at different font sizes.
While that gives you nice sharp looking text, it looks absolutely horrible if you try to change the scale gradually. If you try to animate the font size of some text rendered in this fashion, the thing will seem to shimmer and shudder, because the adjustments made in the name of clarity end up being slightly different at each font size. Even if you're not animating, it can still produce poor results - if you have a single typeface shown at a number of sizes, it can look quite different at each size; if your application has a zoom feature, the character of the text can seem to change significantly as you zoom in and out. (And so can the layout. If you use Microsoft Word, you may have noticed that you sometimes get odd-looking extra wide spaces between certain words. This is the result of Word fighting with GDI32 - Word attempts to keep the on-screen layout as close as possible to how things will look when printing, which means it sometimes clashes with GDI32's grid fitting.)
So WPF offers a different approach to text rendering: it can render text in a way that is as faithful as possible to the original design of the font. This distorts the text less, and it means that you don't get discontinuities as you scale.
The downside is that the text looks blurry, compared to how text rendered by GDI32 looks. (The distortions made by GDI32 are all aimed at improving clarity.)
So in WPF 4.0, Microsoft added the ability to render text in the way GDI32 would. That's what TextOptions.TextFormattingMode="Display" does.
By turning on that option, you are saying "I don't need consistent scaling, and I'd prefer clarity, so generate the same pixels you would have done in GDI32." If you then go on to apply scaling, having told WPF you didn't need scalability, you get crappy results. WPF carefully generated a bitmap representation of the text exactly to your specifications, and you then told it to render that text at a different scale. And so it looks like what it is: a scaled bitmap of some text that was generated for a different resolution.
You could argue that WPF could do something different here: if you apply a scale transform in GDI32 you'd see different behaviour - you'd see the inconsistency at different scales described earlier. If you really want that effect in WPF you can get it by modifying the font size directly. But WPF doesn't prioritise getting that same effect - its goals are to make it possible to get GDI32-style crisp text when you really need it, and to provide consistent scaling by default.
And what you're running into here is the "consistent scaling". Turning on GDI32-style text rendering doesn't break consistent scaling: applying a scale factor (either directly, via a ScaleTransform or indirectly via a Viewbox) will change the dimensions of the visual by exactly the specified scale factor. If it were to re-generate the text visuals by grid fitting to the newly scaled size, the text would come out at a different width. That would actually cause the Viewbox problems: it applies a scale factor based on the content's natural size, designed to make it fit the available space. But if it re-did the grid fit after scaling, that would actually change the width. Because of the inconsistencies inherent in how GDI32 text rendering works, it might not even be possible for the ViewBox to find a suitable scale - it's possible to come up with a piece of text which, when rendered in a particular font, will never come out at 200 pixels wide. For some font sizes, the rounding inherent in grid fitting might bump the size down to, say, 198, and it might stick at that as you make tiny increments in the font size, until you go past some threshold at which point it might jump to 202 pixels.
For a Viewbox attempting to force the text to fit into exactly 200 pixels, that would be a problem. But Viewbox doesn't work that way - it uses WPF's consistent scaling, downstream of the point at which you chose the font size to which GDI32-style text rendering is working. So Viewbox will always be able to do what it is designed to do, but that is task that's fundamentally incompatible with GDI32-style text rendering.
So in short, WPF renders the text for the font size you requested, and then scales the result.
So you have to pick just one feature - you can't have both because that's simply impossible. Either don't attempt to render text in a context in which an arbitrary scale factor may be applied (e.g. Viewbox) or don't turn on GDI32-style text rendering. Otherwise, you get that weird pixelated text that you've encountered.
Ok, bug found. My Window style has the following setter:
<Setter Property="TextOptions.TextFormattingMode" Value="Display"/>
If I set it back to "Ideal" (which is the default value) then it renders the text inside the viewbox correctly. I would say that this is a bug inside WPF. Basically, if you try this:
<Viewbox Height="100" Stretch="Uniform" TextOptions.TextFormattingMode="Display">
<TextBlock FontFamily="Georgia">My Cool Text</TextBlock>
</Viewbox>
You will get the same result as in my initial picture.

Setting the ToolTip in a WPF chart?

I would like to set the ToolTip on my chart line, pie, area, bubble to include both the X and the Y values.
Charting is use is defined here :
xmlns:chartingToolkit="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit"
I've learned that I can use the ControlTemplate to do this and by overriding the entire thing, I can also set the tooltip.
But this also changes things which I like, the random color selection, the status changes etc.
Is there a way to apply only the tooltip binding to all chart series types, without having to override the entire thing for each of the types (that makes for a very long and mostly irrelevant code, which mostly I don't understand and don't care about)
Thanks! (My first post)
...
You have to copy a part of the original source (the style).
Check this site: http://blogs.msdn.com/b/delay/archive/2010/04/22/nobody-likes-a-show-off-today-s-datavisualizationdemos-release-includes-new-demos-showing-off-stacked-series-behavior.aspx
Here you can download this zip file that contains an example project in WPF.
Read the source/style in ChartStyling.xaml and your question will most likely be answered!

Detect whether a font supports variants (like superscript and subscript)

WPF has the Typography.Variants attached property that lets you do superscript and subscript. However, it only works for some fonts. For other fonts, the variant is utterly ignored, and the text is shown normally. (Code sample and screenshot here)
Since it silently falls back to a no-op, I have no idea that anything went wrong; but my user will see lousy behavior.
Is there any way that I can programmatically detect whether a given font supports Typography.Variants? If so, I could provide more meaningful behavior if the user selected a non-variant-supporting font for something that needs superscripts/subscripts.
I looked at GlyphTypeface, since it's the one you use to query whether a font can be embedded, but I didn't see anything there about variants. I also didn't see anything obvious on FontFamily, and the only thing I could find on Typography was the Variants attached property itself (and its getters and setters).
As far as I can tell, WPF provides no information about the available GSUB tables (which tell you this information). Everything is hidden deep within private classes of PresentationCore.
One way would be to use the advanced text services of WPF to create a TextFormatter, and then retrieve the GlyphRuns created by a piece of text with the variants on, and one with the variants off, and then compare the glyph indexes used.
Another way would be to physically examine a font's data through GlyphTypeFace.GetFontStream(). The TrueType font format is not very complicated, so you'll probably find some information on the net on how to parse the binary font data to find information on the GSUB tables.
Note that simply asking wither a variant is supported is also a little ambiguous. A font can say it supports a variant, but nothing requires it to actually provide any meaningful substitutions. Most Adobe fonts provide only a few alphabetical lowercase characters for things like superscript and subscript (not even the entire Latin alphabet, mind you). Which is pretty useless, IMHO, since you can't ask WPF to fake subscripts or superscripts like Word and other word processors do.
Still, it would have been nice if you could simply ask TypeFace.GetSupportedOpenTypeFeatures().

Resources