21

When I try to build the WPF project with .net framework 4.6.2, I got an error, Because the FormattedText() is Obsoleted as below: [Obsolete("Use the PixelsPerDip override", false)] public FormattedText(string textToFormat, CultureInfo culture, FlowDirection flowDirection, Typeface typeface, double emSize, Brush foreground);

The new override method is public FormattedText(string textToFormat, CultureInfo culture, FlowDirection flowDirection, Typeface typeface, double emSize, Brush foreground, double pixelsPerDip);

Q: How can I determine the pixelsPerDip ?

Q: How can I use old constructor without pixelsPerDip?, because the pixelsPerDip is useless for my project.

Mike Nakis
  • 56,297
  • 11
  • 110
  • 142
D.Andy
  • 247
  • 3
  • 9

2 Answers2

30

You need to calculate the DPI of your monitor, see: How can I get the DPI in WPF?

In Addition, with .Net 4.6.2 come new APIs to handle the DPI awareness, so the above methods might be deprecated (e.g. VisualTreeHelper.GetDpi()). See https://blogs.msdn.microsoft.com/dotnet/2016/08/02/announcing-net-framework-4-6-2/ Here is some example code and a Userguide: https://github.com/Microsoft/WPF-Samples/tree/master/PerMonitorDPI

IMHO this pararameter has been added so that your program can be dragged between monitors with different DPIs and still is scaled correctly.

From FromattedText declaration: pixelsPerDip:

The Pixels Per Density Independent Pixel value, which is the equivalent of the scale factor. For example, if the DPI of a screen is 120 (or 1.25 because 120/96 = 1.25) , 1.25 pixel per density independent pixel is drawn. DIP is the unit of measurement used by WPF to be independent of device resolution and DPIs.

If you just have 1 monitor and therefore don't need any DPI changed event handling, use the following for example in the OnLoaded() event of your Window (or in your constructor):

var pixelsPerDip =  VisualTreeHelper.GetDpi(this).PixelsPerDip;
Graviton
  • 81,782
  • 146
  • 424
  • 602
Leguanjoe
  • 316
  • 3
  • 3
  • Thanks Leguanjoe, however my project cannot switch the monitors, So do you know is there a default value I can set ? (e.g." -1") or something else I can use this constructor without get DPI ,thank you in advance – D.Andy Oct 28 '16 at 03:01
  • I would use the VisualTreeHelper method, if you don't want to, I'd go with "1.0" so that the function expects a monitor with 96 DPI. I'm not even sure if this value comes into play, when you only use 1 screen. I tried "5" and still saw no change in the size of the FormattedText. – Leguanjoe Oct 28 '16 at 07:58
  • So I browsed through the developer guide, the reason why setting PixelsPerDip to any value might be the following: – Leguanjoe Oct 28 '16 at 08:02
  • WPF apps are System DPI aware by default, and need to declare themselves to be Per Monitor DPI aware via an app.manifest file. – Leguanjoe Oct 28 '16 at 08:03
  • So if your app is not declared Per Monitor DPI aware (which in your case is true) the pixelsPerDip paramter comes not into play. – Leguanjoe Oct 28 '16 at 08:18
  • I am very appreciate you answer, Thank you Leguanjoe. – D.Andy Oct 31 '16 at 08:14
  • whats the alternative of "VisualTreeHelper.GetDpi", because we use 4.6.1 in our projects and cant upgrade to 4.6.2? – Parag Jun 13 '18 at 10:08
4

The accepted answer is not wrong, but it is a fair amount of text to read at the end of which you still have no direct solution that you can just type in real quick and make the problem go away.

The warning is saying that this specific overload of FormattedText() has been obsoleted, but another one exists which you should use.

So, generally, all you need to do is to replace this:

new FormattedText( ... );

with this:

new FormattedText( ..., 1.0 );

Mike Nakis
  • 56,297
  • 11
  • 110
  • 142