This question already has an answer here:
So we have this really odd issue. Our application is a C#/WinForms app. In our 6.0 release, our application is not DPI aware. In our 6.1 release it has suddenly become DPI aware. In the 6.0 release, if you run it in high DPI, it uses Windows bitmap scaling, which is fine, because that does not affect the screen layouts. In the 6.1 release, because it has for some reason become DPI aware, the user interfaces get mangled. We are not in a position to fix this right now. We have hundreds of screens, so making them all work properly in DPI aware mode will take a lot of time.
We have confirmed this using SysInternals Process Explorer. In our 6.0 release, it shows Unaware, but in our 6.1 release, it initially shows Unaware, but then changes to System Aware. The latter occurs when the code enters from the EXE into our assembly DLL that contains all of our user interface code (our EXE is basically a very thin shell; all it really does is call a Controller class on our presentation layer assembly.)
We have confirmed the following:
- Both versions are built in Release Mode using VSS 2017.
- Both versions target the same .NET Framework (4.5)
- Both versions use the same DevExpress version.
- Both versions have the same application manifest, which does not have the DPI awareness setting enabled.
- Neither versions have any calls to any DPI related Windows APIs.
- Using Sys Internals and some message boxes we determined at what point the 6.1 release becomes aware (entry point into Presentation assembly) and what DLLs are loaded at that point (ours, DevExpress, other dependencies), and then we built a small dummy app that references the same DLLs, and confirmed that these are loaded. That dummy app does not become DPI aware.
- We have compared the main csproj files between both releases and there are no meaningful differences.
- Neither release references anything from WPF.
We don't understand why our 6.1 release has suddenly become DPI aware. We are clueless what else to look at and we need a fix that puts this release back to DPI unaware mode. It's holding up our release. Would really appreciate any pointers. We are willing to try anything at this point.
About the problem reported in this Question:
An application, which is DPI-unaware by design, relying on Windows virtualization to scale its UI content, suddenly (although after some modifications, leading to a minor release update) - and apparently without an observable reason - becomes DPI-Aware (System Aware).
The application also relies on an interpretation of the
app.manifest
<windowsSettings>
, where the absence of a DPI-awareness definition, defaults (for backward compatibility) to DPI-Unaware.There are no direct references to WPF assemblies and no DPI-related API calls.
The application includes third-party components (and, possibly, external dependencies).
Since DPI-Awareness has become a relevant aspect of UI presentation, given the diversity of screens resolutions available (and related DPI scaling settings), most component producers have adapted to High-DPI and their products are DPI-Aware (scale when a DPI change is detected) and make use of DPI-Aware assemblies (often referencing WPF assemblies, DPI-Aware by definition).
When one of these DPI-Aware components is refenced in a project (directly or indirectly), a DPI-Unaware application will become DPI-Aware, when DPI-Awareness has not been disabled explicitly.
The more direct (and recommended) method to declare an assembly DPI-Awareness, is to declare it explicitly in the application manifest.
Refer to Hans Passant answer for an application manifest setting prior to Visual Studio 2017:
How to configure an app to run on a machine with a high DPI setting
In Visual Studio 2015-Upd.1 and Visual Studio 2017
app.manifest
, this setting is already present, it just needs to be uncommented. Set the section:<dpiAware>false</dpiAware>
.Refer to these MSDN articles for more informations:
High DPI desktop application development on Windows
Setting the default DPI awareness for a process
Another method is to set the process context DPI-Awareness using these Windows API functions:
Windows 7
SetProcessDPIAware
Windows 8.1
SetProcessDpiAwareness
Windows 10, version 1703
SetProcessDpiAwarenessContext()
(When opting for a Per-Monitor DPI-Awareness, use
Context_PerMonitorAwareV2
)Windows 10, version 1809 (October 2018)
A new
DPI_AWARENESS_CONTEXT
has been added:DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED
Use the
GetWindowDpiAwarenessContext()
function to retrieve theDPI_AWARENESS_CONTEXT
handle of a Window andGetThreadDpiAwarenessContext()
for theDPI_AWARENESS_CONTEXT
handle of the current thread. ThenGetAwarenessFromDpiAwarenessContext()
to retrive theDPI_AWARENESS
value from theDPI_AWARENESS_CONTEXT
structure.Since DPI-Awareness is thread-based, these settings can be applied to a specific thread. This can be useful when re-designing an user interface to implement DPI-Awareness, to let the System scale a less important component while focusing on the more important functionalities.
SetThreadDpiAwarenessContext
(Same parameter as
SetProcessDpiAwarenessContext()
)Assemblyinfo.cs
If an third-party/external component, which references a WPF assemblies, redefines the DPI-Awareness status of an application, this automatic behaviour can be disabled, inserting a paramert in the Project
Assemblyinfo.cs
: