Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Diagnostics.CodeAnalysis;
using System.Drawing;
using System.Drawing.Drawing2D;
using Microsoft.Win32;
using static Interop;

namespace System.Windows.Forms
Expand Down Expand Up @@ -171,6 +172,45 @@ public static Bitmap CreateScaledBitmap(Bitmap logicalImage, int deviceDpi = 0)
/// </summary>
public static bool IsScalingRequired => DeviceDpi != LogicalDpi;

/// <summary>
/// Retrieve the text scale factor, which is set via Settings > Display > Make Text Bigger.
/// The settings are stored in the registry under HKCU\Software\Microsoft\Accessibility in (DWORD)TextScaleFactor.
/// </summary>
/// <returns>The scaling factor in the range [1.0, 2.25].</returns>
/// <seealso href="https://docs.microsoft.com/windows/uwp/design/input/text-scaling">Windows Text scaling</seealso>
public static float GetTextScaleFactor()
{
// The default(100) and max(225) text scale factor is value what Settings display text scale
// applies and also clamps the text scale factor value between 100 and 225 value.
const short MinTextScaleValue = 100;
const short MaxTextScaleValue = 225;

short textScaleValue = MinTextScaleValue;
try
{
RegistryKey? key = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Accessibility");
if (key is not null && key.GetValue("TextScaleFactor") is int _textScaleValue)
{
textScaleValue = (short)_textScaleValue;
}
}
catch
{
// Failed to read the registry for whatever reason.
#if DEBUG
throw;
#endif
}

// Restore the text scale if it isn't the default value in the valid text scale factor value
if (textScaleValue > MinTextScaleValue && textScaleValue <= MaxTextScaleValue)
{
return (float)textScaleValue / MinTextScaleValue;
}

return 1.0f;
}

/// <summary>
/// scale logical pixel to the factor
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ private static NtDll.RTL_OSVERSIONINFOEX InitVersion()
return info;
}

/// <summary>
/// Is Windows 10 first release or later. (Threshold 1, build 10240, version 1507)
/// </summary>
public static bool IsWindows10_1507OrGreater
=> s_versionInfo.dwMajorVersion >= 10 && s_versionInfo.dwBuildNumber >= 10240;

/// <summary>
/// Is Windows 10 Anniversary Update or later. (Redstone 1, build 14393, version 1607)
/// </summary>
Expand Down
3 changes: 2 additions & 1 deletion src/System.Windows.Forms/src/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
~override System.Windows.Forms.MonthCalendar.OnResize(System.EventArgs e) -> void
~override System.Windows.Forms.MonthCalendar.OnResize(System.EventArgs e) -> void
~static System.Windows.Forms.Application.SetDefaultFont(System.Drawing.Font font) -> void
2 changes: 1 addition & 1 deletion src/System.Windows.Forms/src/Resources/SR.resx
Original file line number Diff line number Diff line change
Expand Up @@ -6495,7 +6495,7 @@ Stack trace where the illegal operation occurred was:
<value>Width must be greater than MinWidth.</value>
</data>
<data name="Win32WindowAlreadyCreated" xml:space="preserve">
<value>SetCompatibleTextRenderingDefault must be called before the first IWin32Window object is created in the application.</value>
<value>{0} must be called before the first IWin32Window object is created in the application.</value>
</data>
<data name="WindowsFormsSetEvent" xml:space="preserve">
<value>Setting event '{0}'</value>
Expand Down
4 changes: 2 additions & 2 deletions src/System.Windows.Forms/src/Resources/xlf/SR.cs.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/System.Windows.Forms/src/Resources/xlf/SR.de.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/System.Windows.Forms/src/Resources/xlf/SR.es.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/System.Windows.Forms/src/Resources/xlf/SR.fr.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/System.Windows.Forms/src/Resources/xlf/SR.it.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/System.Windows.Forms/src/Resources/xlf/SR.ja.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/System.Windows.Forms/src/Resources/xlf/SR.ko.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/System.Windows.Forms/src/Resources/xlf/SR.pl.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/System.Windows.Forms/src/Resources/xlf/SR.pt-BR.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/System.Windows.Forms/src/Resources/xlf/SR.ru.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/System.Windows.Forms/src/Resources/xlf/SR.tr.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/System.Windows.Forms/src/Resources/xlf/SR.zh-Hans.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/System.Windows.Forms/src/Resources/xlf/SR.zh-Hant.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Reflection;
Expand All @@ -30,6 +31,8 @@ public sealed partial class Application
/// Hash table for our event list
/// </summary>
private static EventHandlerList s_eventHandlers;
private static Font s_defaultFont;
private static Font s_defaultFontScaled;
private static string s_startupPath;
private static string s_executablePath;
private static object s_appFileVersion;
Expand Down Expand Up @@ -279,6 +282,8 @@ public static InputLanguage CurrentInputLanguage
internal static bool CustomThreadExceptionHandlerAttached
=> ThreadContext.FromCurrent().CustomThreadExceptionHandlerAttached;

internal static Font DefaultFont => s_defaultFontScaled ?? s_defaultFont;

/// <summary>
/// Gets the path for the executable file that started the application.
/// </summary>
Expand Down Expand Up @@ -1218,6 +1223,31 @@ public static void Run(ApplicationContext context)
internal static void RunDialog(Form form)
=> ThreadContext.FromCurrent().RunMessageLoop(Interop.Mso.msoloop.ModalForm, new ModalApplicationContext(form));

/// <summary>
/// Scale the default font (if it is set) as per the Settings display text scale settings.
/// </summary>
internal static void ScaleDefaultFont()
{
if (s_defaultFont is null || !OsVersion.IsWindows10_1507OrGreater)
{
return;
}

float textScaleValue = DpiHelper.GetTextScaleFactor();

if (s_defaultFontScaled is not null)
{
s_defaultFontScaled.Dispose();
s_defaultFontScaled = null;
}

// Restore the text scale if it isn't the default value in the valid text scale factor value
if (textScaleValue > 1.0f)
{
s_defaultFontScaled = new Font(s_defaultFont.FontFamily, s_defaultFont.Size * textScaleValue);
}
}

/// <summary>
/// Sets the static UseCompatibleTextRenderingDefault field on Control to the value passed in.
/// This switch determines the default text rendering engine to use by some controls that support
Expand All @@ -1227,12 +1257,60 @@ public static void SetCompatibleTextRenderingDefault(bool defaultValue)
{
if (NativeWindow.AnyHandleCreated)
{
throw new InvalidOperationException(SR.Win32WindowAlreadyCreated);
throw new InvalidOperationException(string.Format(SR.Win32WindowAlreadyCreated, nameof(SetCompatibleTextRenderingDefault)));
}

Control.UseCompatibleTextRenderingDefault = defaultValue;
}

/// <summary>
/// Sets the default <see cref="Font"/> for process.
/// </summary>
/// <param name="font">The font to be used as a default across the application.</param>
/// <exception cref="ArgumentNullException"><paramref name="font"/> is <see langword="null"/>.</exception>
/// <exception cref="InvalidOperationException">
/// You can only call this method before the first window is created by your Windows Forms application.
/// </exception>
/// <remarks>
/// <para>
/// The system text scale factor will be applied to the font, i.e. if the default font is set to "Calibri, 11f"
/// and the text scale factor is set to 150% the resulting default font will be set to "Calibri, 16.5f".
/// </para>
/// <para>
/// Users can adjust text scale with the Make text bigger slider on the Settings -> Ease of Access -> Vision/Display screen.
/// </para>
/// </remarks>
/// <seealso href="https://docs.microsoft.com/windows/uwp/design/input/text-scaling">Windows Text scaling</seealso>
public static void SetDefaultFont(Font font)
{
if (font is null)
throw new ArgumentNullException(nameof(font));

if (NativeWindow.AnyHandleCreated)
throw new InvalidOperationException(string.Format(SR.Win32WindowAlreadyCreated, nameof(SetDefaultFont)));

// If user made a prior call to this API with a different custom fonts, we want to clean it up.
if (s_defaultFont is not null)
{
s_defaultFont?.Dispose();
s_defaultFont = null;
s_defaultFontScaled?.Dispose();
s_defaultFontScaled = null;
}

if (font.IsSystemFont)
{
// The system font is managed the .NET runtime, and it is already scaled to the current text scale factor.
// We need to clone it because our reference will no longer be scaled by the .NET runtime.
s_defaultFont = (Font)font.Clone();
}
else
{
s_defaultFont = font;
ScaleDefaultFont();
}
}

/// <summary>
/// Sets the <see cref="HighDpiMode"/> mode for process.
/// </summary>
Expand Down
Loading