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)); }
/// <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); }
/// <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)); }
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%. } }
/// <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)); }
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 });
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); }
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(); } }
/// <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); }
private static bool GetIsPerMonitorDpiSupportWindows81OrAbove() { var awareness = SHCore.GetCurrentProcessDpiAwareness(); return(awareness == ProcessDpiAwareness.PROCESS_PER_MONITOR_DPI_AWARE); }
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(); } }