Changing DPI on Windows 10 makes WPF application blury(in realtime) - wpf

Simillar question has been asked but I don't think accent was on this.
When I change DPI in Display settings my application becomes blury. If I change DPI settings, than log out and log back in, everything is fine.
My question is - why is OS making my application blury when changing DPI but OS apps like Explorer, Settings, Paint and rest are not blury?
Mentioned OS apps are being resized accordingly to DPI and it is obvious their fonts are crystal clear and crisp. Why is this not happening to my application.
I added dpiAware option in manifest but that doesn't seem to change anything.
Just to note again - I am talking about changing DPI in real time and observing how my application acts and how OS apps act.

You might want to look into SnapsToDevicePixels Property of UIElement

Related

Setting/scaling width of control scrollbars

When per-monitor DPI changes (WM_DPICHANGED message), the built-in scrollbars of controls like list view, tree view, rich edit, listbox are not scaled (as expected).
They need to be scaled programmatically.
Though I didn't find any API (neither in Win32, let alone in WinForms) to set scrollbar size.
What API can I use to set scrollbar size (width)?
Or at least how I do get hold of the scrollbar handle? (I assume that internally the scrollbars are separate child controls) Once I have the handle, I assume I can use MoveWindow to resize it (Edit: my assumption was incorrect, as the answer by #Anders shows)
For a background, see High DPI Desktop Application Development on Windows.
There are couple seemingly duplicate questions, but none of them are actually relevant:
Winforms - Adjust width of vertical scrollbar on CheckedListBox
Change width of scrollbars
The answers there either change system-wide settings or work for DataGrid only (that have separate child scrollbar controls available in its interface).
Scrollbars are usually not separate windows. If a window uses the WS_HSCROLL/WS_VSCROLL styles then the scrollbars are implemented in the non-client area of the control itself.
Windows 10 Creators Update is going to introduce something called Per Monitor V2 DPI awareness. This includes child window notifications, "Windows Forms DPI scaling improvements" and "Improved theming behavior". It is also going to automatically scale the non-client area.
In the meantime you can try calling EnableNonClientDpiScaling in WM_NCCREATE (added in the Anniversary Update).
As suggested by #Anders, the Per Monitor V2 DPI awareness in Windows 10 Creators Update resolves this.
To enable Per Monitor V2 DPI awareness, while still supporting old Per Monitor DPI awareness on older Windows 10 builds and Windows 8.1 and DPI awareness on yet older versions of Windows, make your application manifest like this:
<assembly ...>
<!-- ... --->
<asmv3:application>
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<dpiAware>True/PM</dpiAware>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2,PerMonitor</dpiAwareness>
</asmv3:windowsSettings>
</asmv3:application>
</assembly>
References:
High DPI Improvements for Desktop App Developers in the Windows 10 Creators Update – video (archived)
Application Manifests – reference

My WPF app is per-monitor dpi-aware out of the box. I was not expecting that?

I am a bit confused about per-monitor dpi-aware in WPF. I thought you need to do some work to make your windows scale properly on different monitors (as described in Developing a Per-Monitor DPI-Aware WPF Application).
But I've just ran my app on pc with two monitors (2560x1440 and 2160x1440) and the dialogue would automatically scale itself when I move it between monitors. That's on the latest fast ring Windows 10. Am I missing something?
What you see is an example of System scaling when one app window moves to a different monitor with a different DPI. That is because WPF apps are by-default System DPI Aware. As a result, if you notice carefully, you'll see WPF visuals/text gets blurred when the target DPI is higher or they look fuzzy when the target DPI is lower.
Also, note that monitor resolution does not matter for WPF apps, since WPF is device resolution agnostic (it's measurement unit is Device independent Pixels).
Good news : .NET 4.6.2 preview just got released and it hasPer Monitor DPI Awareness out of the box. Check out the developer guide and samples here :
https://github.com/Microsoft/WPF-Samples/tree/master/PerMonitorDPI
Continuing the conversation from comments.
Yes that is the same for Windows 8.1.
And here is the note from your linked post
Windows Presentation Foundation (WPF) applications are by default system DPI-aware.
HTH

When using the WinForms designer, do I always need to have DPI set to 96?

With my current monitor I prefer a DPI setting of 120 pixels per inch (which windows suggests as the default). However, after designing a form, it often lays out incorrectly on systems that don't use 120 pixels per inch.
I'm wondering, is it necessary that I should set my display settings to 96 pixels per inch for whenever I use the designer?
Also, there are some problems when other developers have different DPIs. They open a form in the designer and move something like a text edit control, and suddenly find that it automatically resizes itself too. Then, there's one control that's a different size to the others and we're in a mess.
P.S. I've read related posts. They're all interesting, but didn't answer my question.
How to control the font DPI in .NET WinForms app
C# WinForms disable DPI scaling
WinForms Different DPI Layouts
DPI not scaling properly
Visual Studio and DPI issue
No. You don't need to always have the DPI set to 96 when using the WinForms designer.
If you set the AutoScaleMode property to Dpi then the designer will write the current system DPI into the designer.cs file in the AutoScaleDimensions property for the form. When the designer is used on a system with a different DPI, this information will be used to rescale the form and the designer can be used at a different DPI.
When I tried other scaling modes, this didn't seem to work well. 'None' meant that controls wouldn't scale at runtime, 'Font' seemed to suffer from rounding errors and when the display settings DPI changed, the control sizes could change slightly causing errors.
I also found that for UserControls that are added to forms it is best to set their AutoScaleMode to Inherit. If you use Dpi, then the controls on it get re-scaled twice and will end up being laid out incorrectly.
I came up with the guidelines above after a few hours of experimentation and internet searching where I found the following two articles:
Automatic scaling in Windows Forms
and:
Child controls on a UserControl may get clipped in a system with a lower Font Dpi
I don't think setting your dpi to a different value permanently will help you. The problem is that there are problems when you change the dpi, i.e. the form layout you have isn't able to deal with different dpi's.
I don't have an absolute solution for you, except that you should test with different dpis and see if it produces problems with the form display. It isn't hard to work out what causes problems and you'll learn what to avoid fairly quickly.

How do you detect tablet PC screen rotation in a full screen Silverlight application?

I am working on a Silverlight 4 out of browser (OOB) application on a Windows 7 tablet PC. The majority of the time, the program is in full screen mode. However, if the user rotates the tablet, the application rotates and stays full screen, but is scaled for the previous screen orientation. Taking the application out of full screen and putting it back into full screen rescales everything correctly. Is there any way I can detect when the screen rotates? So far I've tried the app's Resize, LayoutChanged and FullScreenChanged events and have a handler for the main page's SizeChanged event. None of these get fired when the application is rotated in full screen mode.
Per Josh Einstein's suggestion, I tried polling the ActualWidth/Height of the application on a timer. It looks like after the rotation, the ActualWidth/Height values returned from the Silverlight plug-in are the pre-rotated values. Only taking it out of full screen and putting it back in full screen will change the resolution of the plug-in. The HtmlPage.Eval hack didn't work since I am OOB.
The WP7 version of Silverlight has the OnOrientationChanged event, which doesn't seem to be available in the desktop version. Anyone have any ideas?
Great question but as far as I can tell, it doesn't seem to be possible. I tried changing the screen resolution in a virtual machine (orientation change is really just a screen resolution change that results in width being larger than height or vice versa) and could not trigger any layout events.
The issue seems to be that the Silverlight plugin itself is not resized. With an elevated out-of-browser application you could presumably use COM interop with WMI to get the actual screen resolution, but it's kind of hacky. If it's an in-browser application, you could use the HTML DOM. In both cases, you'll probably have to poll for the current screen resolution instead of being notified via an event.
Mister Goodcat has written a blog post about how to get at this information in both scenarios.
I would file it as a Silverlight bug too.

WPF not rendering on remote desktop

I'm having problems with the rendering of a WPF app over a remote desktop connection.
The applications chrome is rendering, but none of the content is coming through, as if the window is not drawing. Instead the previous content of the screen is showing in it's place.
This has been a problem with the application running on both Vista & Win 7, with remote control being taken from XP and Win7.
The problem is not application specific, if I create a new WPF app, with just a textblock on the window, it will also not run. (Neather will the windows preview in VS2008 display.)
Is there some trick to getting WPF running under RDP?
I read on Kevin Dente's blog (from a twitter post) that he was having trouble with WPF apps in virtual machines. While not the same as Remote Desktop, it's possible the problem could be the same. Kevin was able to fix his problem by disabling hardware accelleration by creating a DWORD registry value at
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Avalon.Graphics\DisableHWAcceleration
and then setting it to 1.
His original blog post is here: http://weblogs.asp.net/kdente/archive/2009/10/19/visual-studio-2010-beta-2-editor-performance-fix-running-on-a-virtual-machine.aspx
That may not be your exact solution, but maybe it points you in the right direction.
WPF should render over RDP; it's smart enough to know when it can render in hardware, and when it can't it reverts to its own GDI+ based software rendering. I would make sure you're running .NET Framework 3.5 SP1 on the remote machine, since there were changes to remoting that might pose issues. (See link below.)
I've been developing a WPF app for the past 6 months and it works just fine over RDP. (From Vista and Win7 to XP, Vista and Server 2003.) One important caveat, however, is that it renders using the Classic theme. So if you're using controls that don't have a classic theme, they won't render. If you're just dropping a TextBox on a Window, then obviously that's not your problem.
Check out this question for some links that may be helpful: Are there problems with rendering WPF over Remote Desktop under Windows XP?
I just had this problem with the ribbonwindow not displaying correctly when testing for the first time via RDP - the transparent background was white, the close minimize/maximize buttons were missing, the rounded corners on the bottom of the window were square, and the top row of ribbon buttons were almost impossible to select.
Turns out there was a simple fix for me. Right-click the RDP connection icon (I have it saved on my desktop), select "Edit", then the "experience" tab, and change "detect connection quality automatically" to "LAN (10 Mbps or higher)".
This fixed it for me.
Ade
Did you also try Win7 latest RDP - Win7 connection? The thing is WPF doesn't use GDI to draw elements.
VNC clients (like UltraVNC) probably will do the trick for you as they using much simplier algorithms more like of sending bitmaps.
I have the same problem than the asker. The standard, out-of-the-box Checkbox is not rendering correctly. I can only see if it is checked when hoovering the checkbox. Otherwhise, no difference between checked and unchecked. Important note : It occurs when setting the foreground to white (see here : https://social.msdn.microsoft.com/Forums/vstudio/en-US/1c03db49-7e53-4cbb-9dd1-b328017c4453/wpf-checkbox-and-radiobutton-check-mark-not-showing-under-xp-windows-classic-theme-and-remote?forum=wpf)
Our application used to have this problem with a custom progress bar.
We fixed this by setting the background color of the Border control to White. This leads me to think there is an issue with transparent backgrounds
There is no special trick needed to get WPF content to show across remote desktop. Our WPF-based app renders just fine over RDP (tried from numerous machines) with no problems. We're even using animations, gradients, WriteableBitmap, etc. w/ no problems.

Resources