How to display Unicode control characters in a WPF TextBox? - c#

My users do a lot of bi-directional text editing, it is not uncommon for them to sprinkle the text with some Left-to-right and/or Right-to-left marks. Sometimes they want to see where those marks are located in the text in order to move or delete them.
The TextBox control in Windows Forms offers a default context menu with some Unicode-related entries, one of which is Show Unicode control characters
Enabling this option will force the control to draw the glyphs defined in the corresponding font for those non-printable characters.
For example, if I set the Text property of a TextBox control to "Hello \u200E World!" and enable this option, I will get the LRM character rendered using its glyph as defined in the font file (font used is Segoe UI).
If we open the Segoe UI font in a font-editing software (I used FontForge), we can see that indeed there are glyphs defined for the LRM and RLM code points.
I also found that StringFormatFlags enumeration can be used to control how these characters are rendered in GDI+, specifically by providing the DisplayFormatControl flag to the StringFormat object:
private void Form_Paint(object sender, PaintEventArgs e)
{
var text = "Hello \u200E World!";
var g = e.Graphics;
// Will draw LRM symbol with its representative glyph
var fmt = new StringFormat(StringFormatFlags.DisplayFormatControl);
g.DrawString(text, Font, Brushes.Black, 10, 10, fmt);
}
However, I haven't found anything similar in WPF TextBox or RichTextBox control: the default context menu provides only Copy, Cut and Paste commands and none of the control properties (including attached ones) seem to enable the drawing of control characters with their font-defined glyphs.
Is there a way to draw Unicode control characters with their representative glyphs in WPF TextBox or RichTextBox without resorting to various hacks, such as replacing those characters with other ones in a converter?

Related

Itext 7 and C# - Different font for special characters

Currently I use Custom Font as a default font for all my reports. Lately I was asked to handle special characters in text from "Segoe UI Symbol" font (Custom font still must be default for text).
Let's say that this is my header input text, and [Symbol] is one of "Segoe UI Symbol" symbols:
"This is my pdf [Symbol] report header [Symbol]"
Result that I've got looks like this:
"This is my pdf [X] report header [X]"
[X] - indicates that character cannot be rendered.
When i switch font to "Segoe UI Symbol", special characters will display fine on pdf.
Is there any way to keep custom font for all text but use "Segoe UI Symbol" font for all special characters that cannot be rendered. Like a subsitution font (there was something like this in acrofields). Or is there any other possible solution? Text can contain none, one or multiple symbols.

Looking to bold certain sections of a WPF RTF text through C#

I'm looking for a code-how that can bold selective words and/or lines of text within one of WPF's RichTextBoxes, so that, for example, I could have code that ensures the word bananabread would be automatically set to bold whenever it were typed. Another example of this could be setting an entire line to bold if it begins with the word "Therefore."
I'm aware that you can bold specific lines via XAML, and I know that pressing Ctrl + B can bold specific words while in the editor itself, but how can I go about doing this through C#?

DrawString and TextBox same rendering

Inside OnPaint of a form I am rendering some text on top of an image. For that I call Graphics.DrawString with word wrapping enabled. In order to be able to edit the text I occasionally show (and hide again after editing) an additional TextBox occupying the same rectangle as my hand drawn text and also with word wrapping enabled.
My idea was that the TextBox ought to render the text exactly like the DrawString command. However there appear to be small deviations of text position (and probably text size?). Moreover these deviations seem to vary depending on the chosen font so it is impossible to tune them manually.
While the deviations are not so terrible as such, they lead to irritating consequences when it comes to the automatic word wrapping. For example in the TextBox a word might appear on the second line while it might appear on the first line when rendered with DrawString after accepting the edit. Most of the time it works but for some rectangle sizes it fails.
If transparency had been available for TextBox, I would have used it instead of rendering text manually, but none of the solutions I found has worked.
Is there any hope that I can find out what settings synchronize the rendering between DrawString and TextBox ? Or is the latter an undocumented implementation detail of the win32 textbox?
The essentials of my code (g is a Graphics object from the paint event args):
stringFormat = new StringFormat(StringFormat.GenericDefault);
stringFormat.FormatFlags = StringFormatFlags.NoWrap | StringFormatFlags.NoClip;
stringFormat.Trimming = StringTrimming.None;
stringFormatAutomaticLinebreak = new StringFormat(StringFormat.GenericDefault);
stringFormatAutomaticLinebreak.FormatFlags = StringFormatFlags.NoClip;
stringFormatAutomaticLinebreak.Trimming = StringTrimming.None;
if (Data.IsAutomaticLinebreak)
{
Rectangle boundingRectangle = new Rectangle(Data.TextPosition.X, Data.TextPosition.Y,
Data.WindowSize.Width-Data.TextPosition.X-1, Data.WindowSize.Height-Data.TextPosition.Y-1);
g.DrawString(Data.Text, Data.TextFont, Data.TextBrush, boundingRectangle, stringFormatAutomaticLinebreak);
}
else
{
g.DrawString(Data.Text, Data.TextFont, Data.TextBrush, Data.TextPosition.X, Data.TextPosition.Y, stringFormat);
}
and
surrogateTextBox = new TextBox();
surrogateTextBox.BorderStyle = BorderStyle.None;
surrogateTextBox.Multiline = true;
surrogateTextBox.Text = Data.Text;
surrogateTextBox.Font = Data.TextFont;
surrogateTextBox.Location = new Point(Data.TextPosition.X,Data.TextPosition.Y);
surrogateTextBox.Size = new Size(Data.WindowSize.Width-Data.TextPosition.X-1, Data.WindowSize.Height-Data.TextPosition.Y-1);
surrogateTextBox.WordWrap = Data.IsAutomaticLinebreak;
Controls.Add(surrogateTextBox);

What font is used if a Unicode-character is not found in the selected font (Tahoma)?

I have written a WPF user control that uses Tahoma as a font to display unicode strings, which works fine. However, I have noticed that some eastern asian characters are actually missing in Tahoma, i.e. this font does not support all common Unicode characters.
However, when I display a string that contains some east asian letters, that I suppose are missing in Tahoma.ttf, the character is displayed correctly anyway, instead of a black rectangle that I expected to get for the missing unicode character.
So out of curiosity: is there any fallback mechanism, i.e. does Windows 7 or C# WPF replace the missing characters from a fallback font? Can anybody please explain how exactly this is working, and which font is actually used as a allback?
See the Font Fallback section of the FontFamily reference.
Thanks alot H.B., with your keyword, I was able to find this really helpful ressource from Microsoft, that explains how Font Fallback and Font Linking work:
http://msdn.microsoft.com/en-us/goglobal/bb688134
Here is a good quote:
A user running Windows XP selects the Tahoma font to enter some text first in English, next in Hebrew, and then in Telugu. Since Tahoma is an OpenType font, it provides support for Latin and Hebrew scripts, but does not contain any Telugu glyphs. Uniscribe detects this lack of font support and automatically renders the Telugu script by using its fallback font, which is Gautami.

Prevent combobox from resizing on font change

I have a combo box that has a list of font families in it. As you can guess I'm making a toolstrip for editing fonts in a rich text box control. The problem is when I change fonts it's resizing my combobox.
scrolling through different fonts causes the combo box to become "jumpy" and some fonts have a huge height which is causing for some hilarious problems.
Exhibit A:
Exhibit B:
Yeh... I'll show the code that I have so far... by the way the combobox is just bound to the font families collection.
void box_SelectedIndexChanged(object sender, EventArgs e)
{
String text = ((Font)box.SelectedItem).Name;
Font font = (Font)box.SelectedItem;
BeginInvoke(new Action(() => box.Text = text));
BeginInvoke(new Action(() => box.Font = font));
}
Anyone have any ideas, if I can't find a solution I can just stop the font from changing and just display the name in the default font.
Using a ToolStripComboBox is the problem here I think. The .NET 2.0 ToolItem classes have a lot of residual, erm, features that never got addressed. WPF sucked the resources away. The tool strip is obviously not handling the resize very well. Nor does it make the rest of the form move down when it gets bigger which is by design.
The canonical font combobox uses owner draw to display the fonts in the dropdown list in their regular style. Without changing the font of the box itself. You really don't want the toolstrip to resize, that's just not a great UI.
The only way I can think of doing it is by creating a custom combobox control and deriving from said control. This will give you access to the variable ownerdraw which gives us a little more flexibility without having to mess around with the ItemHeight property. Hooking into one of the events, which dictate that the value of the control has changed.
You could then have a function like the following to calculate the new layout size:
using (Font font = new Font(this.Font.FontFamily, (float)this.PreviewFontSize))
{
Size textSize;
textSize = TextRenderer.MeasureText("yY", font);
_itemHeight = textSize.Height + 2;
}
I tried all these approaches with little success sadly. However I didn't realize it until today when I looked at how microsoft office implements it. They actually use the same font in the combo box for the selected item no matter what font is selected. So as much as I want to make it more custom I'm just going to use a uniform font for whatever font is shown in the selected index.

Categories