Why does WPF render differently on Windows XP vs Windows 7?
I'm using .NET SP1 on both computers..
My layout is like this window that has no toolbar and is set to maximize so it fits the whole screen.
Under that, I have a Viewbox set to use Stretch: Uniform, and under that I have my LayoutRoot.
This way I hoped to get the same layout on all computers, but it seems it doesn't render exactly the same on Windows XP. Some items are a bit smaller and the layout doesn't look that great.
I have tried to change my resoulution on my Windows 7 computer to the same as the Windows XP computer, and it keeps the layout like it is supposed to.
And both computers use 96 DPI.
Windows XP
Windows 7
Took me about three hours to finally figure this out - after much detective work, but now it is pixel perfect!
It appears that WPF on Windows XP and WPF on Windows 7 not only have different default font faces as well as a default font sizes.
I had a problem where fonts were rendering differently on Windows XP from how they were on Windows 7. It was quite critical since the final output was to the printer, and they needed to be identical. It appeared initially that the problem was a difference in line spacing.
Yes - I had the same exact font installed on Windows XP as I was using on Windows 7
Yes - I tried a very generic font (Arial) and still had the same problems.
Yes - Same DPI on both machines.
Yes - Same result whether in a VM (Windows XP Mode) or on a real Windows XP machine.
Eventually I discovered that the fonts where I was specifying an explicit size looked identical on Windows XP, and only the ones where I didn't specify an explicit size were they different.
So here's how I fixed it in my MainWindow.xaml - with a ContentControl to set a default size:
<Grid x:Name="LayoutRoot" Background="#FFDEDEDE" UseLayoutRounding="True">
<ContentControl FontFamily="Segoe UI" FontSize="12">
... window contents ...
</ContentControl>
</Grid>
Note: If you're using Blend you may need to enter FontSize="12" by hand. If you select it from the properties designer it will delete it, because it thinks 12 is already the default!
Like I said my destination was the printer - so I had to do the same for the control being printed.
Where else can I set this default font size? Anyhow, I now have pixel perfect rendering on Windows XP and Windows 7, and they differ only by the cleartype anti-aliasing differences.
Note: UseLayoutRounding is not part of my solution - but I always use it on my root control also.
The default fonts are different
Make a WPF button
<Button x:Name="button" Width="100" Height="25" Content="Button" Click="Button_Click"/>
and code behind:
private void Button_Click(object sender, RoutedEventArgs e)
{
string msg = string.Format("Number of fonts: {1}{0}Font Family: {2}{0}Font Size: {3}",
Environment.NewLine,
button.FontFamily.FamilyNames.Values.Count.ToString(),
button.FontFamily.FamilyNames.Values.First().ToString(),
button.FontSize.ToString());
MessageBox.Show(msg);
}
Run this on each operating system and you will see that the default fonts for XP and Windows7 are different.
Default font for XP is “Tahoma” size 11
Default font for Windows 7 is “Segoe UI” size 12
My experience:
I'm not sure if it is the issue, I noticed Windows 7 uses hardware acceleration to draw the WPF application. Windows XP doesn't.
You can check if this is the case by using something like this:
public partial class App
{
public static int Tier { get { return RenderCapability.Tier >> 16; } }
static App()
{
Console.Out.WriteLine("Render Tier: {0}", Tier);
}
}
Your rendering tier should return 2 if it used full hardware accelerated drawing. 0 = software, 1 = something in the middle if guess
Different versions of Windows have different default fonts (also different versions of the same fonts) and different font rendering engines - as a result the text size is different between systems.
You can try to set the font to the same font and see how it works, maybe try several fonts to check where the difference is smallest.
Related
I am facing display issues with winforms in window 10 OS. The fonts used for forms is 'Estrangelo Edessa’. In windows 10, this font doesn't come installed by default and hence text/content looks ugly (cutoff/improperly sized). So i am thinking to change the font that looks closer to 'Estrangelo Edessa' and will be native to windows 7, 8 and 10. Please suggest one such font.
I suggest trying Verdana or Lucida Sans Unicode as they have similar proportions to Estrangelo Edessa. Alternatively, Calibri is narrower but otherwise similar and nicer to read.
You may also want to look into having your forms size the controls so text is never cut off, just in case. For example, all WinForms controls have a PreferredSize property.
I cannot figure out how to determine how to render a specific OpenType font correctly in WPF (.NET 4.5 / VS2012 / Windows 8). I have a font installed on my computer called "DINPro-BlackItalic".
The file name is: DINPro-BlackItalic.otf
Windows reports the font name is: DINPro-BlackItalic
In WPF, I do something simple, like this:
<TextBlock Text="This is a sample sentence in DINPro-BlackItalic"
FontFamily="DinPro-BlackItalic" FontSize="24" />
or FontFamily="#DinPro-BlackItalic"
This doesn't work (clearly not italic) and it falls back to the default font. I've tried lots of other variations which do work for other fonts in the font directory.
For example, Comic Sans works: FontFamily="Comic Sans MS" (awesome...)
Now, this is why I am really confused: If I just guess at a different way to punctuate the font name, it renders correctly!
This works: FontFamily="Din Pro Black Italic"
In summary, here is a screen shot of different FontFamily settings in WPF:
Two questions:
1) How am I supposed to guess at the right way to tell WPF to render this font? It must have a canonical name registered somewhere but it isn't visible in the filename, file properties, or the Font Name that Windows reports after it has parsed the file.
2) What's worse is that if I'm attempting to render the same font in a desktop application and on the Web, browsers like Chrome on Windows and even IE expect "DINPro-BlackItalic" and will not render the spaced out version of the name. It seems that WPF and windows browsers make mutually exclusive decisions about which Font Name to use to index fonts. How do I work around this for arbitrary fonts?
You can pack the font with the Application, and you can refer it from the project directory.
Say if you place the font inside Fonts Directory in the Project.
You can add as follows,
<TextBlock FontFamily=”/Fonts/DINPro-BlackItalic.otf#DinPro-BlackItalic”/>
So you can be sure the, font gets deployed with the application.
Okay so I think i found the solution..
<TextBlock FontFamily=”/Fonts/DINPro-BlackItalic.otf#Din Pro”/>
or
<TextBlock FontFamily=”/Fonts/DINPro-BlackItalic.otf#Din Pro Black Italic”/>
Havn't tried your code, but This seemed to work for me.. Referencing the path of the file+fontname
Opentype files have a commen name they share. And this is where it gets tricky, because you can only see this name if you install the font on your pc, and check it in the familytree. Like you showed before in your question:
FontFamily="Din Pro Black Italic"
This is my experience, not 100% sure that i'm correct, only that it works for me :)
For WPF, Better to try it with designer for selecting the font for Textblock
For Browsers, It can be tried with Label or any other UI controls to display.
The syntax that works for me is:
/{Application Name};component/{Font Folder in Project}/#{Font Name (not filename)}
Example:
/ApplicationName;component/Fonts/#Proxima Nova Lt
I have applied SmallCaps as shown below, but it doesn't seem to have any effect on in the browser or in a design window.
<TextBlock Text="Text Here !" Typography.Capitals="SmallCaps"/>
Why is Typography.Capitals parameter ignored? Are there any settings that need to be enabled for this ?
UPDATE
It seems that for these properties to work, the font used must support them. Silverlight can not perform magic with the font, it can only work with the features built into the font itself. And it seems that there are some differences between different versions of Windows, which made this even more confusing. I have tried this on Windows 7 and 8 using the following fonts:
Gabriola, Georgia, Verdana, Arial, Comic Sans MS, Calibri, Segoe UI, Portable User Interface
On both Win7 and 8 the only properties that ever worked were SmallCaps and AllSmallCaps. None of the other settings made any difference whatsoever, neither on Win7 or Win8. On Windows 8 these two properties worked for all the fonts listed above. On Windows 7 the only fonts where they did work were Calibri and Gabriola. I then started looking into the versions of the fonts installed on the two different machines. It turns out they are different. For example, on my Win7 machine both Verdana and Segoe UI is of version 5.05. On the Win8 machine Verdana is version 5.31 and Segoe UI is version 5.28.
So I think this is why we get different results on different machines. It has nothing to do with Silverlight, but with the versions of the fonts installed on the client machine. The version of Verdana installed on Win7 has no support for SmallCaps and AllSmallCaps, but the version that comes with Win8 does have that support.
END UPDATE
I am definitely seeing a difference with SmallCaps and AllSmallCaps. The rest of the values don't seem to do anything. It could depend on the FontFamily used I suppose. Any way, the following code renders like the screen shot below.
<ContentControl FontSize="18"
FontFamily="Segoe UI">
<StackPanel>
<TextBlock Text="Writing Some Text Here in the Text Block. AllPetiteCaps"
Typography.Capitals="AllPetiteCaps"></TextBlock>
<TextBlock Text="Writing Some Text Here in the Text Block. AllSmallCaps"
Typography.Capitals="AllSmallCaps"></TextBlock>
<TextBlock Text="Writing Some Text Here in the Text Block. Normal"
Typography.Capitals="Normal"></TextBlock>
<TextBlock Text="Writing Some Text Here in the Text Block. PetiteCaps"
Typography.Capitals="PetiteCaps"></TextBlock>
<TextBlock Text="Writing Some Text Here in the Text Block. SmallCaps"
Typography.Capitals="SmallCaps"></TextBlock>
<TextBlock Text="Writing Some Text Here in the Text Block. Titling"
Typography.Capitals="Titling"></TextBlock>
<TextBlock Text="Writing Some Text Here in the Text Block. Unicase"
Typography.Capitals="Unicase"></TextBlock>
</StackPanel>
</ContentControl>
I'm not sure how much difference there is between WPF and Silverlight on this, but apparently for WPF the font has to be an OpenType font. According to wpf.2000things.com:
WPF includes a Typography class, which allows setting various attached properties for textual elements. These properties only affect text that is rendered using an OpenType font.
And in Programming WPF, 2nd Edition:
WPF supports both TrueType and OpenType fonts. OpenType fonts often contain
many alternates to the basic set of character shapes in order to support advanced
typographical functionality. If you are using a low-level text-handling feature such as
GlyphRun, you can use these alternates directly, referring to them by glyph index. But
if you are using the higher-level elements, such as TextBlock or the FlowDocument
viewers, these can locate and use the appropriate glyphs for you. You can control
which character shapes are used with the attached properties defined by the
Typography class.
I don't want my WPF GUI to scale with Windows font size options (DPI). It's not just a matter of specifying a fixed font size on the UserControl because scaling affects images and borders in the UserControl. Is there a property that I can set on the UserControl to turn off scalling? If not, how can I do that?
You could scale down your UserControl based on the current DPI setting. For example, if you wrapped your UserControl with the following DpiDecorator, then it should look the same regardless of the DPI setting:
public class DpiDecorator : Decorator {
public DpiDecorator() {
this.Loaded += (s, e) => {
Matrix m = PresentationSource.FromVisual(this).CompositionTarget.TransformToDevice;
ScaleTransform dpiTransform = new ScaleTransform(1 / m.M11, 1 / m.M22);
if (dpiTransform.CanFreeze)
dpiTransform.Freeze();
this.LayoutTransform = dpiTransform;
};
}
}
Or you could move that logic to your UserControl.
The code to obtain the DPI scale factor was from this blog post.
Windows includes a compatibility helper for buggy applications that fail under high-dpi settings:
Be sure to leave off (or turn off) "Use Windows XP style DPI scaling":
And be sure your application does not have a "dpiAware" entry in its assembly manifest.
Windows will lie to your application, tell it that it's 96dpi, and then the graphics card will scale the entire window up for you.
Everything will be slightly fuzzy, and generally unpleasant to use, but it will work well enough until you can fix the buggy WinForm control.
Note: The dpiAware manifest entry lets your application tell Windows that it wants to opt-out of the dpi-scaling. Applications only add this item if they've been tested at high-dpi.
in addition the the DpiDecorator, you will also need to fix the font size of your items. For example, in Windows XP, if your setting is set to Large Fonts, Menu Item font size is set to 14 and is also scaled up using the DPI setting, so if you don't fix your MenuItem font size or any other UI item font, you will get Window's default value for this item type. Also remember that a user can manually change the font size/font face for other items...
I've got a C# 3.0 Windows Forms app built with VS2008 (previously ported from C# 1.1) that looks fine on a WinXP 32bit PC but has jacked proportions on Win7 64bit laptop.
I'm finding references to the lack of support on Win7 for Tahoma 8, which the app uses. Do I need to redesign my dialog using Tahoma 9 to get it to display well on all 3 OSes?
Here are my initial measurements (cm) of a group box containing radio buttons and a button:
OS, Resolution, GroupBox HxW, RadioButton HxW
XP, 1024 x 768, 7.5 x 6.75, 0.75 x 4.4
7, 1024 x 768, 6.8 x 6.3, 0.8 x 5.0
7, 1680 x 1050, 4.9 x 4.5, 0.55 x 3.5
The problem is basically that on the different OS's, the group box has its proportions changed differently than the radios it contains, such that radios and labels that fit fine in the group box in XP run out of bounds (both x & y axis) on 7. Similarly, the text on the button grew more than the button. This happens even when I dial down the 7 box's resolution to match the XP box. The GroupBox's font is larger than that of the radios, but even when I made them equal I saw no improvement.
I think it has something to do with the fact that the application was originally created with an older version of C# and then ported. I say this because I just created a new (empty) Windows forms project using VS2008, and for every control in my app that isn't displaying correctly on win7, when I copy that control to the new app and run it on win7 it resizes correctly. There must be some high level property in the app that the controls are inheriting.
What causes this and what can I do about it?
Thanks in advance.
The main form's 'AutoScaleMode' was set to 'Font'. Setting it to 'DPI' fixed it (although that created other problems due to the code not anticipating being resized on startup...null refs, but I can deal with those).
Tergiver gets double credit for pointing me to the form's property sheet and for me taking this long to notice the obvious property :)