/// <summary> /// Sets the DPI awareness. If not available on the current OS, it falls back to the next possible. /// </summary> /// <returns>true/false - If the process DPI awareness is successfully set, returns true. Otherwise false.</returns> internal static bool SetWinformsApplicationDpiAwareness(HighDpiMode highDpiMode) { NativeMethods.PROCESS_DPI_AWARENESS dpiFlag = NativeMethods.PROCESS_DPI_AWARENESS.PROCESS_DPI_UNINITIALIZED; // For Windows 10 RS2 and above if (ApiHelper.IsApiAvailable(ExternDll.User32, nameof(SafeNativeMethods.SetProcessDpiAwarenessContext))) { int rs2AndAboveDpiFlag; switch (highDpiMode) { case HighDpiMode.SystemAware: rs2AndAboveDpiFlag = NativeMethods.DPI_AWARENESS_CONTEXT_SYSTEM_AWARE; break; case HighDpiMode.PerMonitor: rs2AndAboveDpiFlag = NativeMethods.DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE; break; case HighDpiMode.PerMonitorV2: // Necessary for RS1, since this SetProcessDpiAwarenessContext IS available here. rs2AndAboveDpiFlag = SafeNativeMethods.IsValidDpiAwarenessContext(NativeMethods.DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) ? NativeMethods.DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 : NativeMethods.DPI_AWARENESS_CONTEXT_SYSTEM_AWARE; break; case HighDpiMode.DpiUnawareGdiScaled: // Let's make sure, we do not try to set a value which has been introduced in later Windows releases. rs2AndAboveDpiFlag = SafeNativeMethods.IsValidDpiAwarenessContext(NativeMethods.DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED) ? NativeMethods.DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED : NativeMethods.DPI_AWARENESS_CONTEXT_UNAWARE; break; default: rs2AndAboveDpiFlag = NativeMethods.DPI_AWARENESS_CONTEXT_UNAWARE; break; } return(SafeNativeMethods.SetProcessDpiAwarenessContext(rs2AndAboveDpiFlag)); } // For operating systems Windows 8.1 to Windows 10 RS1 version. else if (ApiHelper.IsApiAvailable(ExternDll.ShCore, nameof(SafeNativeMethods.SetProcessDpiAwareness))) { switch (highDpiMode) { case HighDpiMode.DpiUnaware: case HighDpiMode.DpiUnawareGdiScaled: dpiFlag = NativeMethods.PROCESS_DPI_AWARENESS.PROCESS_DPI_UNAWARE; break; case HighDpiMode.SystemAware: dpiFlag = NativeMethods.PROCESS_DPI_AWARENESS.PROCESS_SYSTEM_DPI_AWARE; break; case HighDpiMode.PerMonitor: case HighDpiMode.PerMonitorV2: dpiFlag = NativeMethods.PROCESS_DPI_AWARENESS.PROCESS_PER_MONITOR_DPI_AWARE; break; default: dpiFlag = NativeMethods.PROCESS_DPI_AWARENESS.PROCESS_SYSTEM_DPI_AWARE; break; } return(SafeNativeMethods.SetProcessDpiAwareness(dpiFlag) == NativeMethods.S_OK); } // For operating systems windows 7 to windows 8 else if (ApiHelper.IsApiAvailable(ExternDll.User32, nameof(SafeNativeMethods.SetProcessDPIAware))) { switch (highDpiMode) { case HighDpiMode.DpiUnaware: case HighDpiMode.DpiUnawareGdiScaled: // We can return, there is nothing to set if we assume we're already in DpiUnaware. return(true); case HighDpiMode.SystemAware: case HighDpiMode.PerMonitor: case HighDpiMode.PerMonitorV2: dpiFlag = NativeMethods.PROCESS_DPI_AWARENESS.PROCESS_SYSTEM_DPI_AWARE; break; } if (dpiFlag == NativeMethods.PROCESS_DPI_AWARENESS.PROCESS_SYSTEM_DPI_AWARE) { return(SafeNativeMethods.SetProcessDPIAware()); } } return(false); }
/// <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 (ApiHelper.IsApiAvailable(ExternDll.User32, nameof(CommonUnsafeNativeMethods.GetThreadDpiAwarenessContext))) { DpiAwarenessContext dpiAwareness = CommonUnsafeNativeMethods.GetThreadDpiAwarenessContext(); if (CommonUnsafeNativeMethods.TryFindDpiAwarenessContextsEqual(dpiAwareness, DpiAwarenessContext.DPI_AWARENESS_CONTEXT_SYSTEM_AWARE)) { return(HighDpiMode.SystemAware); } if (CommonUnsafeNativeMethods.TryFindDpiAwarenessContextsEqual(dpiAwareness, DpiAwarenessContext.DPI_AWARENESS_CONTEXT_UNAWARE)) { return(HighDpiMode.DpiUnaware); } if (CommonUnsafeNativeMethods.TryFindDpiAwarenessContextsEqual(dpiAwareness, DpiAwarenessContext.DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2)) { return(HighDpiMode.PerMonitorV2); } if (CommonUnsafeNativeMethods.TryFindDpiAwarenessContextsEqual(dpiAwareness, DpiAwarenessContext.DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE)) { return(HighDpiMode.PerMonitor); } if (CommonUnsafeNativeMethods.TryFindDpiAwarenessContextsEqual(dpiAwareness, DpiAwarenessContext.DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED)) { return(HighDpiMode.DpiUnawareGdiScaled); } } // For operating systems windows 8.1 to Windows 10 redstone 1 version. else if (ApiHelper.IsApiAvailable(ExternDll.ShCore, nameof(SafeNativeMethods.GetProcessDpiAwareness))) { CAPS.PROCESS_DPI_AWARENESS processDpiAwareness; SafeNativeMethods.GetProcessDpiAwareness(IntPtr.Zero, out processDpiAwareness); switch (processDpiAwareness) { case CAPS.PROCESS_DPI_AWARENESS.PROCESS_DPI_UNAWARE: return(HighDpiMode.DpiUnaware); case CAPS.PROCESS_DPI_AWARENESS.PROCESS_SYSTEM_DPI_AWARE: return(HighDpiMode.SystemAware); case CAPS.PROCESS_DPI_AWARENESS.PROCESS_PER_MONITOR_DPI_AWARE: return(HighDpiMode.PerMonitor); } } // For operating systems windows 7 to windows 8 else if (ApiHelper.IsApiAvailable(ExternDll.User32, nameof(SafeNativeMethods.IsProcessDPIAware))) { return(SafeNativeMethods.IsProcessDPIAware() ? HighDpiMode.SystemAware : HighDpiMode.DpiUnaware); } // We should never get here, except someone ported this with force to < Windows 7. return(HighDpiMode.DpiUnaware); }