示例#1
0
        internal static void InitializeDpiHelperForWinforms()
        {
            if (s_isInitializeDpiHelperForWinforms)
            {
                return;
            }

            // initialize shared fields
            Initialize();

            if (OsVersion.IsWindows10_1607OrGreater)
            {
                // We are on Windows 10/1603 or greater, but we could still be DpiUnaware or SystemAware, so let's find that out...
                IntPtr hProcess = Kernel32.OpenProcess(
                    Kernel32.ProcessAccessOptions.QUERY_INFORMATION,
                    BOOL.FALSE,
                    Kernel32.GetCurrentProcessId());
                SHCore.GetProcessDpiAwareness(hProcess, out SHCore.PROCESS_DPI_AWARENESS processDpiAwareness);

                // Only if we're not, it makes sense to query for PerMonitorV2 awareness from now on, if needed.
                if (!(processDpiAwareness == SHCore.PROCESS_DPI_AWARENESS.UNAWARE ||
                      processDpiAwareness == SHCore.PROCESS_DPI_AWARENESS.SYSTEM_AWARE))
                {
                    s_doesNeedQueryForPerMonitorV2Awareness = true;
                }
            }

            if (IsScalingRequired || s_doesNeedQueryForPerMonitorV2Awareness)
            {
                s_isScalingRequirementMet = true;
            }

            s_isInitializeDpiHelperForWinforms = true;
        }
        public override Dpi GetDpiForMonitor(IntPtr hMonitor)
        {
            uint dpiX, dpiY;

            SHCore.GetDpiForMonitor(hMonitor, MonitorDpiType.Default, out dpiX, out dpiY);

            return(new Dpi(dpiX, dpiY));
        }
示例#3
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 (OsVersion.IsWindows10_1607OrGreater)
            {
                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);
                }
            }
            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);
        }
示例#4
0
        /// <summary>
        /// ディスプレイモニターの DPI 設定値を取得します。
        /// </summary>
        /// <param name="hMonitor">ディスプレイモニタの HMONITOR</param>
        /// <param name="dpiType">DPI の種類。既定値は <see cref="MonitorDpiType.Default"/> (<see cref="MonitorDpiType.EffectiveDpi"/> と同値) です。</param>
        /// <returns><paramref name="hWnd"/> のウィンドウが描画されているモニターの DPI 設定値。サポートされていないシステムの場合は <see cref="Dpi.Default"/>。</returns>
        private static Dpi GetDpiForMonitor(IntPtr hMonitor, MonitorDpiType dpiType)
        {
            if (!IsSupported)
            {
                return(Dpi.Default);
            }

            uint dpiX = 1, dpiY = 1;

            SHCore.GetDpiForMonitor(hMonitor, dpiType, out dpiX, out dpiY);

            return(new Dpi(dpiX, dpiY));
        }
示例#5
0
 public static uint GetDpi(this System.Windows.Forms.Screen screen, DpiType dpiType)
 {
     try
     {
         var monitor = User32.MonitorFromPoint(screen.Bounds.Location, User32.MONITOR_DEFAULTTONEAREST);
         SHCore.GetDpiForMonitor(monitor, dpiType, out var dpiX, out var _);
         return(dpiX);
     }
     catch (System.DllNotFoundException)
     {
         return(96);                // On Windows <8, just assume scaling 100%.
     }
 }
示例#6
0
        /// <summary>
        /// 指定したハンドルのウィンドウが描画されているモニターの DPI 設定値を取得します。
        /// </summary>
        /// <param name="hWnd">DPI を取得する対象の Win32 ウィンドウを示すウィンドウ ハンドル。</param>
        /// <param name="dpiType">DPI の種類。既定値は <see cref="MonitorDpiType.Default"/> (<see cref="MonitorDpiType.EffectiveDpi"/> と同値) です。</param>
        /// <returns><paramref name="hWnd"/> のウィンドウが描画されているモニターの DPI 設定値。サポートされていないシステムの場合は <see cref="Dpi.Default"/>。</returns>
        public static Dpi GetDpi(IntPtr hWnd, MonitorDpiType dpiType = MonitorDpiType.Default)
        {
            if (!IsSupported)
            {
                return(Dpi.Default);
            }

            var hmonitor = User32.MonitorFromWindow(
                hWnd,
                MonitorDefaultTo.MONITOR_DEFAULTTONEAREST);

            uint dpiX = 1, dpiY = 1;

            SHCore.GetDpiForMonitor(hmonitor, dpiType, ref dpiX, ref dpiY);

            return(new Dpi(dpiX, dpiY));
        }
示例#7
0
        private static bool GetPerMonitorAware()
        {
            if (!OsVersion.IsWindows10_1607OrGreater)
            {
                return(false);
            }

            HRESULT result = SHCore.GetProcessDpiAwareness(
                IntPtr.Zero,
                out SHCore.PROCESS_DPI_AWARENESS processDpiAwareness);

            Debug.Assert(result.Succeeded(), $"Failed to get ProcessDpi HRESULT: {result}");
            Debug.Assert(Enum.IsDefined(typeof(SHCore.PROCESS_DPI_AWARENESS), processDpiAwareness));

            return(result.Succeeded() && processDpiAwareness switch
            {
                SHCore.PROCESS_DPI_AWARENESS.UNAWARE => false,
                SHCore.PROCESS_DPI_AWARENESS.SYSTEM_AWARE => false,
                SHCore.PROCESS_DPI_AWARENESS.PER_MONITOR_AWARE => true,
                _ => true
            });
示例#8
0
        public void Run()
        {
            // DPI Awareness API is not available on older OS's, but they work in
            // physical pixels anyway, so we just ignore if the call fails.
            try
            {
                SHCore.SetProcessDpiAwareness(PROCESS_DPI_AWARENESS.Process_Per_Monitor_DPI_Aware);
            }
            catch (DllNotFoundException)
            {
                Debug.WriteLine("No SHCore.DLL. No problem.");
            }

            // Make sure we catch CTRL-C hard-exit of program.
            _ctrlCHandler = new Kernel32.ConsoleEventDelegate(ConsoleEventCallback);
            Kernel32.SetConsoleCtrlHandler(_ctrlCHandler, true);

            Debug.WriteLine(_screenSet = new ScreenSet());

            // Get notified of any screen configuration changes.
            SystemEvents.DisplaySettingsChanged += Event_DisplaySettingsChanged;

            //User32.ShowWindow(Kernel32.GetConsoleWindow(), User32.SW_HIDE);

            //--Keep a reference to the delegate, so it does not get garbage collected.
            _mouseHookDelegate = LLMouseHookCallback;
            _llMouseHookhand   = SetHook(User32.WH_MOUSE_LL, _mouseHookDelegate);

            Debug.WriteLine("");

            // This is the one that runs "forever" while the application is alive, and handles
            // events, etc. This application is ABSOLUTELY ENTIRELY driven by the LLMouseHook
            // and DisplaySettingsChanged events.
            System.Windows.Forms.Application.Run();

            Debug.WriteLine("Exiting!!!");
            UnsetHook(ref _llMouseHookhand);
        }
示例#9
0
        private void InitializeAddIn()
        {
            Splash splash = null;

            try
            {
                if (_isInitialized)
                {
                    // The add-in is already initialized. See:
                    // The strange case of the add-in initialized twice
                    // http://msmvps.com/blogs/carlosq/archive/2013/02/14/the-strange-case-of-the-add-in-initialized-twice.aspx
                    return;
                }

                var configLoader = new XmlPersistanceService <GeneralSettings>
                {
                    FilePath =
                        Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
                                     "Rubberduck", "rubberduck.config")
                };
                var configProvider = new GeneralConfigProvider(configLoader);

                _initialSettings = configProvider.Create();
                if (_initialSettings != null)
                {
                    try
                    {
                        var cultureInfo = CultureInfo.GetCultureInfo(_initialSettings.Language.Code);
                        Dispatcher.CurrentDispatcher.Thread.CurrentUICulture = cultureInfo;
                    }
                    catch (CultureNotFoundException)
                    {
                    }

                    try
                    {
                        if (_initialSettings.SetDpiUnaware)
                        {
                            SHCore.SetProcessDpiAwareness(PROCESS_DPI_AWARENESS.Process_DPI_Unaware);
                        }
                    }
                    catch (Exception)
                    {
                        Debug.Assert(false, "Could not set DPI awareness.");
                    }
                }
                else
                {
                    Debug.Assert(false, "Settings could not be initialized.");
                }

                if (_initialSettings?.CanShowSplash ?? false)
                {
                    splash = new Splash
                    {
                        // note: IVersionCheck.CurrentVersion could return this string.
                        Version = $"version {Assembly.GetExecutingAssembly().GetName().Version}"
                    };
                    splash.Show();
                    splash.Refresh();
                }

                Startup();
            }
            catch (Win32Exception)
            {
                System.Windows.Forms.MessageBox.Show(Resources.RubberduckUI.RubberduckReloadFailure_Message,
                                                     RubberduckUI.RubberduckReloadFailure_Title,
                                                     MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
            catch (Exception exception)
            {
                _logger.Fatal(exception);
                System.Windows.Forms.MessageBox.Show(
#if DEBUG
                    exception.ToString(),
#else
                    exception.Message.ToString(),
#endif
                    RubberduckUI.RubberduckLoadFailure, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                splash?.Dispose();
            }
        }
示例#10
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)
        {
            if (OsVersion.IsWindows10_1703OrGreater)
            {
                // SetProcessDpiAwarenessContext 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 SetProcessDpiAwarenessContext IS available here.
                    rs2AndAboveDpiFlag = User32.IsValidDpiAwarenessContext(User32.DPI_AWARENESS_CONTEXT.PER_MONITOR_AWARE_V2).IsTrue() ?
                                         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).IsTrue() ?
                                         User32.DPI_AWARENESS_CONTEXT.UNAWARE_GDISCALED :
                                         User32.DPI_AWARENESS_CONTEXT.UNAWARE;
                    break;

                default:
                    rs2AndAboveDpiFlag = User32.DPI_AWARENESS_CONTEXT.UNAWARE;
                    break;
                }
                return(User32.SetProcessDpiAwarenessContext(rs2AndAboveDpiFlag).IsTrue());
            }
            else if (OsVersion.IsWindows8_1OrGreater)
            {
                // 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;
                }

                return(SHCore.SetProcessDpiAwareness(dpiFlag) == HRESULT.S_OK);
            }
            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)
                {
                    return(User32.SetProcessDPIAware().IsTrue());
                }
            }

            return(false);
        }
示例#11
0
        private static bool GetIsPerMonitorDpiSupportWindows81OrAbove()
        {
            var awareness = SHCore.GetCurrentProcessDpiAwareness();

            return(awareness == ProcessDpiAwareness.PROCESS_PER_MONITOR_DPI_AWARE);
        }
示例#12
0
        private void InitializeAddIn()
        {
            Splash2021 splash = null;

            try
            {
                if (_isInitialized)
                {
                    // The add-in is already initialized. See:
                    // The strange case of the add-in initialized twice
                    // http://msmvps.com/blogs/carlosq/archive/2013/02/14/the-strange-case-of-the-add-in-initialized-twice.aspx
                    return;
                }

                var pathProvider   = PersistencePathProvider.Instance;
                var configLoader   = new XmlPersistenceService <GeneralSettings>(pathProvider, _fileSystem);
                var configProvider = new GeneralConfigProvider(configLoader);

                _initialSettings = configProvider.Read();
                if (_initialSettings != null)
                {
                    try
                    {
                        var cultureInfo = CultureInfo.GetCultureInfo(_initialSettings.Language.Code);
                        Dispatcher.CurrentDispatcher.Thread.CurrentUICulture = cultureInfo;
                    }
                    catch (CultureNotFoundException)
                    {
                    }

                    try
                    {
                        if (_initialSettings.SetDpiUnaware)
                        {
                            SHCore.SetProcessDpiAwareness(PROCESS_DPI_AWARENESS.Process_DPI_Unaware);
                        }
                    }
                    catch (Exception)
                    {
                        Debug.Assert(false, "Could not set DPI awareness.");
                    }
                }
                else
                {
                    Debug.Assert(false, "Settings could not be initialized.");
                }

                if (_initialSettings?.CanShowSplash ?? false)
                {
                    splash = new Splash2021();
                    splash.Show();
                    splash.Refresh();
                }

                Startup();
            }
            catch (Win32Exception)
            {
                System.Windows.Forms.MessageBox.Show(Resources.RubberduckUI.RubberduckReloadFailure_Message,
                                                     RubberduckUI.RubberduckReloadFailure_Title,
                                                     MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
            catch (Exception exception)
            {
                _logger.Fatal(exception);
                // TODO Use Rubberduck Interaction instead and provide exception stack trace as
                // an optional "more info" collapsible section to eliminate the conditional.
                MessageBox.Show(
#if DEBUG
                    exception.ToString(),
#else
                    exception.Message.ToString(),
#endif
                    RubberduckUI.RubberduckLoadFailure, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                splash?.Dispose();
            }
        }