From 9c62cc9a416a2a1287f4d01e7ba5f41db4113cad Mon Sep 17 00:00:00 2001 From: Jumar Macato Date: Thu, 17 Oct 2019 02:35:28 +0800 Subject: [PATCH 1/3] Fix #3069 --- .../Interop/UnmanagedMethods.cs | 9 ++++++++ src/Windows/Avalonia.Win32/ScreenImpl.cs | 22 ++++++++++++++++--- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs index d37bec3334..2c6425e26c 100644 --- a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs +++ b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs @@ -1031,6 +1031,9 @@ namespace Avalonia.Win32.Interop [DllImport("shcore.dll")] public static extern long GetDpiForMonitor(IntPtr hmonitor, MONITOR_DPI_TYPE dpiType, out uint dpiX, out uint dpiY); + [DllImport("gdi32.dll")] + public static extern int GetDeviceCaps(IntPtr hdc, DEVICECAP nIndex); + [DllImport("shcore.dll")] public static extern void GetScaleFactorForMonitor(IntPtr hMon, out uint pScale); @@ -1147,6 +1150,12 @@ namespace Avalonia.Win32.Interop } } + public enum DEVICECAP + { + HORZRES = 8, + DESKTOPHORZRES = 118 + } + public enum PROCESS_DPI_AWARENESS { PROCESS_DPI_UNAWARE = 0, diff --git a/src/Windows/Avalonia.Win32/ScreenImpl.cs b/src/Windows/Avalonia.Win32/ScreenImpl.cs index e77aa07bcd..6a89c9bf24 100644 --- a/src/Windows/Avalonia.Win32/ScreenImpl.cs +++ b/src/Windows/Avalonia.Win32/ScreenImpl.cs @@ -28,9 +28,25 @@ namespace Avalonia.Win32 (IntPtr monitor, IntPtr hdcMonitor, ref Rect lprcMonitor, IntPtr data) => { MONITORINFO monitorInfo = MONITORINFO.Create(); - if (GetMonitorInfo(monitor,ref monitorInfo)) + if (GetMonitorInfo(monitor, ref monitorInfo)) { - GetDpiForMonitor(monitor, MONITOR_DPI_TYPE.MDT_EFFECTIVE_DPI, out var x, out _); + var dpi = 1.0; + try + { + GetDpiForMonitor(monitor, MONITOR_DPI_TYPE.MDT_EFFECTIVE_DPI, out var x, out _); + dpi = (double)x; + } + catch (DllNotFoundException) + { + var hdc = GetDC(IntPtr.Zero); + + double virtW = GetDeviceCaps(hdc, DEVICECAP.HORZRES); + double physW = GetDeviceCaps(hdc, DEVICECAP.DESKTOPHORZRES); + + dpi = (96d * physW / virtW); + + ReleaseDC(IntPtr.Zero, hdc); + } RECT bounds = monitorInfo.rcMonitor; RECT workingArea = monitorInfo.rcWork; @@ -40,7 +56,7 @@ namespace Avalonia.Win32 new PixelRect(workingArea.left, workingArea.top, workingArea.right - workingArea.left, workingArea.bottom - workingArea.top); screens[index] = - new WinScreen((double)x / 96.0d, avaloniaBounds, avaloniaWorkArea, monitorInfo.dwFlags == 1, + new WinScreen(dpi / 96.0d, avaloniaBounds, avaloniaWorkArea, monitorInfo.dwFlags == 1, monitor); index++; } From bbdf0592c1c1cd021d96314bdefd386cfdcf4fb0 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Wed, 16 Oct 2019 21:34:59 +0100 Subject: [PATCH 2/3] check for shcore rather than exception. --- src/Windows/Avalonia.Win32/ScreenImpl.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Windows/Avalonia.Win32/ScreenImpl.cs b/src/Windows/Avalonia.Win32/ScreenImpl.cs index 6a89c9bf24..fda3b77727 100644 --- a/src/Windows/Avalonia.Win32/ScreenImpl.cs +++ b/src/Windows/Avalonia.Win32/ScreenImpl.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using Avalonia.Platform; +using Avalonia.Win32.Interop; using static Avalonia.Win32.Interop.UnmanagedMethods; namespace Avalonia.Win32 @@ -31,12 +32,13 @@ namespace Avalonia.Win32 if (GetMonitorInfo(monitor, ref monitorInfo)) { var dpi = 1.0; - try - { + + if (UnmanagedMethods.ShCoreAvailable) + { GetDpiForMonitor(monitor, MONITOR_DPI_TYPE.MDT_EFFECTIVE_DPI, out var x, out _); dpi = (double)x; } - catch (DllNotFoundException) + else { var hdc = GetDC(IntPtr.Zero); From 1c9e158a4c2d655cfd1319b3af46203364467608 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Wed, 16 Oct 2019 21:58:39 +0100 Subject: [PATCH 3/3] use getproc address to check for GetDpiForMonitor. --- src/Windows/Avalonia.Win32/ScreenImpl.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Windows/Avalonia.Win32/ScreenImpl.cs b/src/Windows/Avalonia.Win32/ScreenImpl.cs index fda3b77727..df4cf7fa19 100644 --- a/src/Windows/Avalonia.Win32/ScreenImpl.cs +++ b/src/Windows/Avalonia.Win32/ScreenImpl.cs @@ -32,8 +32,10 @@ namespace Avalonia.Win32 if (GetMonitorInfo(monitor, ref monitorInfo)) { var dpi = 1.0; - - if (UnmanagedMethods.ShCoreAvailable) + + var shcore = LoadLibrary("shcore.dll"); + var method = GetProcAddress(shcore, nameof(GetDpiForMonitor)); + if (method != IntPtr.Zero) { GetDpiForMonitor(monitor, MONITOR_DPI_TYPE.MDT_EFFECTIVE_DPI, out var x, out _); dpi = (double)x;