Exemplo n.º 1
0
        /// <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 == DpiAwarenessContext.DPI_AWARENESS_CONTEXT_UNSPECIFIED && dpiContextB == DpiAwarenessContext.DPI_AWARENESS_CONTEXT_UNSPECIFIED)
            {
                return(true);
            }
            if (ApiHelper.IsApiAvailable(ExternDll.User32, nameof(CommonUnsafeNativeMethods.AreDpiAwarenessContextsEqual)))
            {
                return(AreDpiAwarenessContextsEqual(dpiContextA, dpiContextB));
            }

            return(false);
        }
Exemplo n.º 2
0
        /// <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)
        {
            // User.32 AreDpiAwarenessContextsEqual API returns false when sent custom values like DPI_AWARENESS_CONTEXT_UNSPECIFIED, but it is true when both are equal to the same custom value.
            if (dpiContextA == DpiAwarenessContext.DPI_AWARENESS_CONTEXT_UNSPECIFIED && dpiContextB == DpiAwarenessContext.DPI_AWARENESS_CONTEXT_UNSPECIFIED)
            {
                return(true);
            }

            if (ApiHelper.IsApiAvailable(ExternDll.User32, "AreDpiAwarenessContextsEqual"))
            {
                return(AreDpiAwarenessContextsEqual(dpiContextA, dpiContextB));
            }

            return(false);
        }
Exemplo n.º 3
0
        /*
         *      // Dpi awareness context values. Matching windows values.
         *      public static readonly DPI_AWARENESS_CONTEXT DPI_AWARENESS_CONTEXT_UNAWARE = (-1);
         *      public static readonly DPI_AWARENESS_CONTEXT DPI_AWARENESS_CONTEXT_SYSTEM_AWARE = (-2);
         *      public static readonly DPI_AWARENESS_CONTEXT DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE = (-3);
         *      public static readonly DPI_AWARENESS_CONTEXT DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 = (-4);
         *      public static readonly DPI_AWARENESS_CONTEXT DPI_AWARENESS_CONTEXT_UNSPECIFIED = (0);*/

        internal static DpiAwarenessContext GetDpiAwarenessContextForWindow(IntPtr hWnd)
        {
            DpiAwarenessContext dpiAwarenessContext = DpiAwarenessContext.DPI_AWARENESS_CONTEXT_UNSPECIFIED;

            if (ApiHelper.IsApiAvailable(ExternDll.User32, "GetWindowDpiAwarenessContext") &&
                ApiHelper.IsApiAvailable(ExternDll.User32, "GetAwarenessFromDpiAwarenessContext"))
            {
                // Works only >= Windows 10/1607
                IntPtr        awarenessContext = GetWindowDpiAwarenessContext(hWnd);
                DPI_AWARENESS awareness        = GetAwarenessFromDpiAwarenessContext(awarenessContext);
                dpiAwarenessContext = ConvertToDpiAwarenessContext(awareness);
            }

            return(dpiAwarenessContext);
        }
Exemplo n.º 4
0
 /// <summary>
 /// Tries to set thread dpi awareness context
 /// </summary>
 /// <returns> returns old thread dpi awareness context if API is available in this version of OS. otherwise, return IntPtr.Zero.</returns>
 public static DpiAwarenessContext TrySetThreadDpiAwarenessContext(DpiAwarenessContext dpiContext)
 {
     if (ApiHelper.IsApiAvailable(ExternDll.User32, nameof(CommonUnsafeNativeMethods.SetThreadDpiAwarenessContext)))
     {
         if (dpiContext == DpiAwarenessContext.DPI_AWARENESS_CONTEXT_UNSPECIFIED)
         {
             throw new ArgumentException(nameof(dpiContext), dpiContext.ToString());
         }
         return(SetThreadDpiAwarenessContext(dpiContext));
     }
     else
     {
         // legacy OS that does not have this API available.
         return(DpiAwarenessContext.DPI_AWARENESS_CONTEXT_UNSPECIFIED);
     }
 }
Exemplo n.º 5
0
        internal static void InitializeDpiHelperForWinforms()
        {
            if (isInitializeDpiHelperForWinforms)
            {
                return;
            }

            // initialize shared fields
            try {
                Initialize();

                // We are in Windows 10/1603 or greater when this API is present.
                if (ApiHelper.IsApiAvailable(ExternDll.User32, nameof(CommonUnsafeNativeMethods.GetThreadDpiAwarenessContext)))
                {
                    // We are on Windows 10/1603 or greater all right, but we could still be DpiUnaware or SystemAware, so let's find that out...
                    NativeMethods.PROCESS_DPI_AWARENESS processDpiAwareness;
                    var    currentProcessId = SafeNativeMethods.GetCurrentProcessId();
                    IntPtr hProcess         = SafeNativeMethods.OpenProcess(SafeNativeMethods.PROCESS_QUERY_INFORMATION, false, currentProcessId);
                    var    result           = SafeNativeMethods.GetProcessDpiAwareness(hProcess, out processDpiAwareness);

                    // Only if we're not, it makes sense to query for PerMonitorV2 awareness from now on, if needed.
                    if (!(processDpiAwareness == CAPS.PROCESS_DPI_AWARENESS.PROCESS_DPI_UNAWARE ||
                          processDpiAwareness == CAPS.PROCESS_DPI_AWARENESS.PROCESS_SYSTEM_DPI_AWARE))
                    {
                        doesNeedQueryForPerMonitorV2Awareness = true;
                    }
                }
            } catch (Exception e) {
                if (Environment.OSVersion.Platform == System.PlatformID.Win32NT)
                {
                    throw e;
                }
                else
                {
                    Console.WriteLine($"Failed DpiHelper {e}");
                }
            }

            if (IsScalingRequired || doesNeedQueryForPerMonitorV2Awareness)
            {
                isScalingRequirementMet = true;
            }

            isInitializeDpiHelperForWinforms = true;
        }
Exemplo n.º 6
0
        /// <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)
        {
            CAPS.PROCESS_DPI_AWARENESS dpiFlag = CAPS.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 = CAPS.DPI_AWARENESS_CONTEXT_SYSTEM_AWARE;
                    break;

                case HighDpiMode.PerMonitor:
                    rs2AndAboveDpiFlag = CAPS.DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE;
                    break;

                case HighDpiMode.PerMonitorV2:
                    // Necessary for RS1, since this SetProcessDpiAwarenessContext IS available here.
                    rs2AndAboveDpiFlag = SafeNativeMethods.IsValidDpiAwarenessContext(CAPS.DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) ?
                                         CAPS.DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 :
                                         CAPS.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(CAPS.DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED) ?
                                         CAPS.DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED :
                                         CAPS.DPI_AWARENESS_CONTEXT_UNAWARE;
                    break;

                default:
                    rs2AndAboveDpiFlag = CAPS.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 = CAPS.PROCESS_DPI_AWARENESS.PROCESS_DPI_UNAWARE;
                    break;

                case HighDpiMode.SystemAware:
                    dpiFlag = CAPS.PROCESS_DPI_AWARENESS.PROCESS_SYSTEM_DPI_AWARE;
                    break;

                case HighDpiMode.PerMonitor:
                case HighDpiMode.PerMonitorV2:
                    dpiFlag = CAPS.PROCESS_DPI_AWARENESS.PROCESS_PER_MONITOR_DPI_AWARE;
                    break;

                default:
                    dpiFlag = CAPS.PROCESS_DPI_AWARENESS.PROCESS_SYSTEM_DPI_AWARE;
                    break;
                }

                return(SafeNativeMethods.SetProcessDpiAwareness(dpiFlag) == CAPS.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 = CAPS.PROCESS_DPI_AWARENESS.PROCESS_SYSTEM_DPI_AWARE;
                    break;
                }

                if (dpiFlag == CAPS.PROCESS_DPI_AWARENESS.PROCESS_SYSTEM_DPI_AWARE)
                {
                    return(SafeNativeMethods.SetProcessDPIAware());
                }
            }
            return(false);
        }
Exemplo n.º 7
0
        /// <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)))
            {
                SafeNativeMethods.GetProcessDpiAwareness(IntPtr.Zero, out CAPS.PROCESS_DPI_AWARENESS 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);
        }