简体   繁体   中英

How to create a scaling and size-changing Per-Monitor DPI-aware application that is backwards compatible with Windows 7?

I'm new to WPF (and to DPI-awareness APIs) and am writing an application for running in Windows 7, 8.1, and 10. I use multiple monitors with different per-monitor DPI settings, and am interested in making my application as compatible as possible across desktop configurations.

I already know that is possible to add a Manifest to a WPF application, uncomment the section for DPI awareness, and set it to True/PM . This successfully allows the program to be Per-Monitor DPI-aware in Windows 8.1 and 10 (thus looking clean and sharp over various monitors), but run as System-aware in Windows 7.

But can we do one step better? Microsoft provides a neat tutorial here that shows how to create a Per-Monitor DPI-Aware WPF application. What they do is actually create a new object in C++ to replace <Window> that uses Windows 8.1 APIs to not only detect the DPI change between the monitors, but then to re-size the application at runtime, effectively matching the change in DPI. The end result is that not only is the app Per-DPI aware and sharp looking, but when switching between large and small monitors of various sizes, the app looks to the user to change the same physical size (in inches or centimeters) on screen.

The downside to Microsoft's Win32 code is that it is not backwards compatible with Windows 7. Trying to run in 7 results in the application crashing.

I've gone through this article on Dr.Dobbs and this one by Kenny Karr but don't understand the APIs well enough to make things work.

Does anyone know of a way to do something similar to Microsoft's code, where in Windows 8.1 and newer, an application that is Per-Monitor aware will actually change size when moving between monitors, but runs as System-Aware in Windows 7?

I haven't looked at the code, but my guess is that the crash is caused because of missing native methods in win 7. The way to fix this is to modify the native methods wrapper, for example (pseudo code):

public int GetDPIOfMonitor(IntPtr monitorHandle)
{
   if (Enviroment.OSVersion >= "6.2") // win 8 and above
   {
      return NativeMethods.PInvoke.GetMonitorDPI(monitorHandle);
   }
   else return systemDPI;
}

This way you don't crash under 7, because you are not calling the missing native methods.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM