public void ParkingWindow_SystemAware() { // run tests only on Windows 10 versions that support thread dpi awareness. if (!PlatformDetection.IsWindows10Version1803OrGreater) { return; } // set thread awareness context to PermonitorV2(PMv2). // if process/thread is not in PMv2, calling 'EnterDpiAwarenessScope' is a no-op and that is by design. // In this case, we will be setting thread to PMv2 mode and then scope to UNAWARE IntPtr originalAwarenessContext = User32.SetThreadDpiAwarenessContext(User32.DPI_AWARENESS_CONTEXT.PER_MONITOR_AWARE_V2); try { using (DpiHelper.EnterDpiAwarenessScope(User32.DPI_AWARENESS_CONTEXT.SYSTEM_AWARE)) { using var control = new Control(); ThreadContext ctx = GetContextForHandle(new HandleRef(this, control.Handle)); Assert.NotNull(ctx); ParkingWindow parkingWindow = ctx.GetParkingWindowForContext(User32.DPI_AWARENESS_CONTEXT.SYSTEM_AWARE); Assert.NotNull(parkingWindow); IntPtr dpiContext = User32.GetWindowDpiAwarenessContext(parkingWindow.Handle); Assert.True(User32.AreDpiAwarenessContextsEqual(User32.DPI_AWARENESS_CONTEXT.SYSTEM_AWARE, dpiContext)); } } finally { // reset back to original awareness context. User32.SetThreadDpiAwarenessContext(originalAwarenessContext); } }
/// <summary> /// Gets the DPI awareness. /// </summary> /// <returns>The thread's/process' current HighDpi mode</returns> internal static HighDpiMode GetWinformsApplicationDpiAwareness() { // For Windows 10 RS2 and above if (OsVersion.IsWindows10_1607OrGreater) { IntPtr dpiAwareness = User32.GetThreadDpiAwarenessContext(); if (User32.AreDpiAwarenessContextsEqual(dpiAwareness, User32.DPI_AWARENESS_CONTEXT.SYSTEM_AWARE)) { return(HighDpiMode.SystemAware); } if (User32.AreDpiAwarenessContextsEqual(dpiAwareness, User32.DPI_AWARENESS_CONTEXT.UNAWARE)) { return(HighDpiMode.DpiUnaware); } if (User32.AreDpiAwarenessContextsEqual(dpiAwareness, User32.DPI_AWARENESS_CONTEXT.PER_MONITOR_AWARE_V2)) { return(HighDpiMode.PerMonitorV2); } if (User32.AreDpiAwarenessContextsEqual(dpiAwareness, User32.DPI_AWARENESS_CONTEXT.PER_MONITOR_AWARE)) { return(HighDpiMode.PerMonitor); } if (User32.AreDpiAwarenessContextsEqual(dpiAwareness, User32.DPI_AWARENESS_CONTEXT.UNAWARE_GDISCALED)) { return(HighDpiMode.DpiUnawareGdiScaled); } } else if (OsVersion.IsWindows8_1OrGreater) { SHCore.GetProcessDpiAwareness(IntPtr.Zero, out SHCore.PROCESS_DPI_AWARENESS processDpiAwareness); switch (processDpiAwareness) { case SHCore.PROCESS_DPI_AWARENESS.UNAWARE: return(HighDpiMode.DpiUnaware); case SHCore.PROCESS_DPI_AWARENESS.SYSTEM_AWARE: return(HighDpiMode.SystemAware); case SHCore.PROCESS_DPI_AWARENESS.PER_MONITOR_AWARE: return(HighDpiMode.PerMonitor); } } else { // Available on Vista and higher return(User32.IsProcessDPIAware().IsTrue() ? HighDpiMode.SystemAware : HighDpiMode.DpiUnaware); } // We should never get here, except someone ported this with force to < Windows 7. return(HighDpiMode.DpiUnaware); }
/// <summary> /// Tries to compare two DPIawareness context values. Return true if they were equal. /// Return false when they are not equal or underlying OS does not support this API. /// </summary> /// <returns>true/false</returns> public static bool TryFindDpiAwarenessContextsEqual(DpiAwarenessContext?dpiContextA, DpiAwarenessContext?dpiContextB) { if (dpiContextA == null) { return(dpiContextB == null); // true if both null but not either } else if (dpiContextB == null) { return(false); // because we know A is not null } if (AreDpiAwarenessContextsEqualIsAvailable()) { return(User32.AreDpiAwarenessContextsEqual((DpiAwarenessContext)dpiContextA, (DpiAwarenessContext)dpiContextB)); } // legacy OS that does not have this API available. return(false); }