Created
September 27, 2021 12:22
-
-
Save ryancheung/1b96eb98e2c07d1c95afd570f1e0eae2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Runtime.InteropServices; | |
public static class SHCore | |
{ | |
public enum PROCESS_DPI_AWARENESS : int | |
{ | |
UNAWARE = 0, | |
SYSTEM_AWARE = 1, | |
PER_MONITOR_AWARE = 2 | |
} | |
[DllImport("SHCore.dll", ExactSpelling = true)] | |
public static extern int SetProcessDpiAwareness(PROCESS_DPI_AWARENESS value); | |
} | |
public static class User32 | |
{ | |
[DllImport("user32.dll", ExactSpelling = true)] | |
[return: MarshalAs(UnmanagedType.Bool)] | |
public static extern bool SetProcessDPIAware(); | |
[DllImport("User32.dll", ExactSpelling = true)] | |
[return: MarshalAs(UnmanagedType.Bool)] | |
public static extern bool SetProcessDpiAwarenessContext(IntPtr value); | |
[DllImport("User32.dll", ExactSpelling = true)] | |
[return: MarshalAs(UnmanagedType.Bool)] | |
public static extern bool IsValidDpiAwarenessContext(IntPtr value); | |
public static IntPtr UNSPECIFIED_DPI_AWARENESS_CONTEXT = IntPtr.Zero; | |
public static class DPI_AWARENESS_CONTEXT | |
{ | |
public static readonly IntPtr UNAWARE = (IntPtr)(-1); | |
public static readonly IntPtr SYSTEM_AWARE = (IntPtr)(-2); | |
public static readonly IntPtr PER_MONITOR_AWARE = (IntPtr)(-3); | |
public static readonly IntPtr PER_MONITOR_AWARE_V2 = (IntPtr)(-4); | |
public static readonly IntPtr UNAWARE_GDISCALED = (IntPtr)(-5); | |
} | |
} | |
public static class DpiHelper | |
{ | |
/// <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> | |
public static bool SetApplicationDpiAwareness(HighDpiMode highDpiMode) | |
{ | |
bool success = false; | |
if (OperatingSystem.IsWindowsVersionAtLeast(10)) | |
{ | |
// SetProcessIntPtr needs Windows 10 RS2 and above | |
IntPtr rs2AndAboveDpiFlag; | |
switch (highDpiMode) | |
{ | |
case HighDpiMode.SystemAware: | |
rs2AndAboveDpiFlag = User32.DPI_AWARENESS_CONTEXT.SYSTEM_AWARE; | |
break; | |
case HighDpiMode.PerMonitor: | |
rs2AndAboveDpiFlag = User32.DPI_AWARENESS_CONTEXT.PER_MONITOR_AWARE; | |
break; | |
case HighDpiMode.PerMonitorV2: | |
// Necessary for RS1, since this SetProcessIntPtr IS available here. | |
rs2AndAboveDpiFlag = User32.IsValidDpiAwarenessContext(User32.DPI_AWARENESS_CONTEXT.PER_MONITOR_AWARE_V2) | |
? User32.DPI_AWARENESS_CONTEXT.PER_MONITOR_AWARE_V2 | |
: User32.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 = User32.IsValidDpiAwarenessContext(User32.DPI_AWARENESS_CONTEXT.UNAWARE_GDISCALED) | |
? User32.DPI_AWARENESS_CONTEXT.UNAWARE_GDISCALED | |
: User32.DPI_AWARENESS_CONTEXT.UNAWARE; | |
break; | |
default: | |
rs2AndAboveDpiFlag = User32.DPI_AWARENESS_CONTEXT.UNAWARE; | |
break; | |
} | |
success = User32.SetProcessDpiAwarenessContext(rs2AndAboveDpiFlag); | |
} | |
else if (OperatingSystem.IsWindowsVersionAtLeast(8)) | |
{ | |
// 8.1 introduced SetProcessDpiAwareness | |
SHCore.PROCESS_DPI_AWARENESS dpiFlag; | |
switch (highDpiMode) | |
{ | |
case HighDpiMode.DpiUnaware: | |
case HighDpiMode.DpiUnawareGdiScaled: | |
dpiFlag = SHCore.PROCESS_DPI_AWARENESS.UNAWARE; | |
break; | |
case HighDpiMode.SystemAware: | |
dpiFlag = SHCore.PROCESS_DPI_AWARENESS.SYSTEM_AWARE; | |
break; | |
case HighDpiMode.PerMonitor: | |
case HighDpiMode.PerMonitorV2: | |
dpiFlag = SHCore.PROCESS_DPI_AWARENESS.PER_MONITOR_AWARE; | |
break; | |
default: | |
dpiFlag = SHCore.PROCESS_DPI_AWARENESS.SYSTEM_AWARE; | |
break; | |
} | |
success = SHCore.SetProcessDpiAwareness(dpiFlag) == 0; | |
} | |
else | |
{ | |
// Vista or higher has SetProcessDPIAware | |
SHCore.PROCESS_DPI_AWARENESS dpiFlag = (SHCore.PROCESS_DPI_AWARENESS)(-1); | |
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 = SHCore.PROCESS_DPI_AWARENESS.SYSTEM_AWARE; | |
break; | |
} | |
if (dpiFlag == SHCore.PROCESS_DPI_AWARENESS.SYSTEM_AWARE) | |
{ | |
success = User32.SetProcessDPIAware(); | |
} | |
} | |
return success; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment