diff --git a/src/Windows/Perspex.Win32/Interop/UnmanagedMethods.cs b/src/Windows/Perspex.Win32/Interop/UnmanagedMethods.cs index 02aefb4106..e8ba9bab16 100644 --- a/src/Windows/Perspex.Win32/Interop/UnmanagedMethods.cs +++ b/src/Windows/Perspex.Win32/Interop/UnmanagedMethods.cs @@ -718,7 +718,6 @@ namespace Perspex.Win32.Interop [DllImport("kernel32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] public static extern IntPtr GlobalLock(IntPtr handle); - [DllImport("kernel32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] public static extern bool GlobalUnlock(IntPtr handle); @@ -737,6 +736,35 @@ namespace Perspex.Win32.Interop [DllImport("comdlg32.dll")] public static extern int CommDlgExtendedError(); + [DllImport("shcore.dll")] + public static extern void SetProcessDpiAwareness(PROCESS_DPI_AWARENESS value); + + [DllImport("shcore.dll")] + public static extern long GetDpiForMonitor(IntPtr hmonitor, MONITOR_DPI_TYPE dpiType, out uint dpiX, out uint dpiY); + + [DllImport("shcore.dll")] + public static extern void GetScaleFactorForMonitor(IntPtr hMon, out uint pScale); + + [DllImport("user32.dll")] + public static extern IntPtr MonitorFromPoint(POINT pt, uint dwFlags); + + public const uint MONITOR_DEFAULTTONULL = 0x00000000; + public const uint MONITOR_DEFAULTTOPRIMARY = 0x00000001; + public const uint MONITOR_DEFAULTTONEAREST = 0x00000002; + + public enum PROCESS_DPI_AWARENESS { + PROCESS_DPI_UNAWARE = 0, + PROCESS_SYSTEM_DPI_AWARE = 1, + PROCESS_PER_MONITOR_DPI_AWARE = 2 + } + + public enum MONITOR_DPI_TYPE { + MDT_EFFECTIVE_DPI = 0, + MDT_ANGULAR_DPI = 1, + MDT_RAW_DPI = 2, + MDT_DEFAULT = MDT_EFFECTIVE_DPI + } + public enum ClipboardFormat { CF_TEXT = 1, diff --git a/src/Windows/Perspex.Win32/Win32Platform.cs b/src/Windows/Perspex.Win32/Win32Platform.cs index 89c6646b0c..19f0795a56 100644 --- a/src/Windows/Perspex.Win32/Win32Platform.cs +++ b/src/Windows/Perspex.Win32/Win32Platform.cs @@ -26,21 +26,38 @@ namespace Perspex.Win32 private UnmanagedMethods.WndProc _wndProcDelegate; private IntPtr _hwnd; - + private double scale = 1.0; private readonly List _delegates = new List(); public Win32Platform() { + HandleDPI(); CreateMessageWindow(); } + private void HandleDPI() { + // Declare that this process is aware of per monitor DPI + UnmanagedMethods.SetProcessDpiAwareness(UnmanagedMethods.PROCESS_DPI_AWARENESS.PROCESS_PER_MONITOR_DPI_AWARE); + + // Get the DPI for the main monitor, and set the scaling factor + UnmanagedMethods.POINT pt = new UnmanagedMethods.POINT() { X = 1, Y = 1 }; + var hMonitor = UnmanagedMethods.MonitorFromPoint(pt, UnmanagedMethods.MONITOR_DEFAULTTONEAREST); + + // TODO: Check for failure + uint dpix, dpiy; + UnmanagedMethods.GetDpiForMonitor(hMonitor, UnmanagedMethods.MONITOR_DPI_TYPE.MDT_EFFECTIVE_DPI, out dpix, out dpiy); + + // Set scale based on x DPI + scale = dpix / 100.0; + } + public Size DoubleClickSize => new Size( UnmanagedMethods.GetSystemMetrics(UnmanagedMethods.SystemMetric.SM_CXDOUBLECLK), UnmanagedMethods.GetSystemMetrics(UnmanagedMethods.SystemMetric.SM_CYDOUBLECLK)); public TimeSpan DoubleClickTime => TimeSpan.FromMilliseconds(UnmanagedMethods.GetDoubleClickTime()); - public double RenderScalingFactor { get; } = 1; - public double LayoutScalingFactor { get; } = 1; + public double RenderScalingFactor { get { return scale; } } + public double LayoutScalingFactor { get { return scale; } } public static void Initialize() {