diff --git a/src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/CheckBoxModernAdapter.cs b/src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/CheckBoxModernAdapter.cs index 920d8553c6f..5634dab7b7b 100644 --- a/src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/CheckBoxModernAdapter.cs +++ b/src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/CheckBoxModernAdapter.cs @@ -1,4 +1,4 @@ -// Licensed to the .NET Foundation under one or more agreements. +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Drawing; @@ -80,21 +80,27 @@ internal override LayoutOptions CommonLayout() private void PaintCore(PaintEventArgs e) { Graphics graphics = e.GraphicsInternal; - ParentBackgroundRenderer.Paint( - Control, - graphics, - Control.ClientRectangle, - Control.BackColor); + bool useControlBackColor = !Control.BackColor.HasTransparency() + && (Control.ShouldSerializeBackColor() || !Control.UseVisualStyleBackColor); + + if (useControlBackColor) + { + using var backBrush = Control.BackColor.GetCachedSolidBrushScope(); + graphics.FillRectangle(backBrush, Control.ClientRectangle); + } + else + { + ParentBackgroundRenderer.Paint( + Control, + graphics, + Control.ClientRectangle, + Control.BackColor); + } LayoutData layout = Layout(e).Layout(); AdjustFocusRectangle(layout); PaintBackgroundImage(e); - Color? customOnColor = Control.ShouldSerializeBackColor() - && Control.BackColor.A == byte.MaxValue - ? Control.BackColor - : null; - Color? customBorderColor = Control.FlatAppearance.BorderColor.IsEmpty ? null : Control.FlatAppearance.BorderColor; @@ -107,7 +113,7 @@ private void PaintCore(PaintEventArgs e) Control.Enabled, Control.MouseIsOver, Control.Focused && Control.ShowFocusCues, - customOnColor, + customOnColor: null, customBorderColor); PaintImage(e, layout); @@ -117,11 +123,16 @@ private void PaintCore(PaintEventArgs e) : Application.IsDarkModeEnabled ? Color.FromArgb(0xF0, 0xF0, 0xF0) : SystemColors.WindowText; + Color disabledTextBackColor = Control.ShouldSerializeBackColor() + && Control.BackColor.A == byte.MaxValue + ? Control.BackColor + : Control.Parent?.BackColor ?? Control.BackColor; + Color textColor = Control.Enabled ? preferredTextColor : ModernControlColorMath.GetDisabledTextColor( preferredTextColor, - Control.Parent?.BackColor ?? Control.BackColor); + disabledTextBackColor); PaintField(e, layout, PaintRender(e).Calculate(), textColor, drawFocus: true); } diff --git a/src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/RadioButtonModernAdapter.cs b/src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/RadioButtonModernAdapter.cs index ebf45535516..86a49fc998a 100644 --- a/src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/RadioButtonModernAdapter.cs +++ b/src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/RadioButtonModernAdapter.cs @@ -1,4 +1,4 @@ -// Licensed to the .NET Foundation under one or more agreements. +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Drawing; @@ -79,21 +79,27 @@ internal override LayoutOptions CommonLayout() private void PaintCore(PaintEventArgs e) { Graphics graphics = e.GraphicsInternal; - ParentBackgroundRenderer.Paint( - Control, - graphics, - Control.ClientRectangle, - Control.BackColor); + bool useControlBackColor = !Control.BackColor.HasTransparency() + && (Control.ShouldSerializeBackColor() || !Control.UseVisualStyleBackColor); + + if (useControlBackColor) + { + using var backBrush = Control.BackColor.GetCachedSolidBrushScope(); + graphics.FillRectangle(backBrush, Control.ClientRectangle); + } + else + { + ParentBackgroundRenderer.Paint( + Control, + graphics, + Control.ClientRectangle, + Control.BackColor); + } LayoutData layout = Layout(e).Layout(); AdjustFocusRectangle(layout); PaintBackgroundImage(e); - Color? customOnColor = Control.ShouldSerializeBackColor() - && Control.BackColor.A == byte.MaxValue - ? Control.BackColor - : null; - Color? customBorderColor = Control.FlatAppearance.BorderColor.IsEmpty ? null : Control.FlatAppearance.BorderColor; @@ -106,7 +112,7 @@ private void PaintCore(PaintEventArgs e) Control.Enabled, Control.MouseIsOver, Control.Focused && Control.ShowFocusCues, - customOnColor, + customOnColor: null, customBorderColor); PaintImage(e, layout); @@ -116,11 +122,16 @@ private void PaintCore(PaintEventArgs e) : Application.IsDarkModeEnabled ? Color.FromArgb(0xF0, 0xF0, 0xF0) : SystemColors.WindowText; + Color disabledTextBackColor = Control.ShouldSerializeBackColor() + && Control.BackColor.A == byte.MaxValue + ? Control.BackColor + : Control.Parent?.BackColor ?? Control.BackColor; + Color textColor = Control.Enabled ? preferredTextColor : ModernControlColorMath.GetDisabledTextColor( preferredTextColor, - Control.Parent?.BackColor ?? Control.BackColor); + disabledTextBackColor); PaintField(e, layout, PaintRender(e).Calculate(), textColor, drawFocus: true); } diff --git a/src/test/unit/System.Windows.Forms/System/Windows/Forms/CheckBoxTests.cs b/src/test/unit/System.Windows.Forms/System/Windows/Forms/CheckBoxTests.cs index 3680393822d..b96ab2bd694 100644 --- a/src/test/unit/System.Windows.Forms/System/Windows/Forms/CheckBoxTests.cs +++ b/src/test/unit/System.Windows.Forms/System/Windows/Forms/CheckBoxTests.cs @@ -571,7 +571,7 @@ public void CheckBox_AppearanceChanged_RecreatesModernAdapter() [InlineData(CheckState.Unchecked, false)] [InlineData(CheckState.Checked, true)] [InlineData(CheckState.Indeterminate, true)] - public void CheckBox_ModernGlyph_RendersAccentForCheckedStates(CheckState checkState, bool expectedAccent) + public void CheckBox_ModernGlyph_UsesExplicitBackColorWithoutTintingCheckedGlyph(CheckState checkState, bool expectedAccent) { if (SystemInformation.HighContrast) { @@ -582,6 +582,7 @@ public void CheckBox_ModernGlyph_RendersAccentForCheckedStates(CheckState checkS using CheckBox box = new() { BackColor = Color.Red, + UseVisualStyleBackColor = true, CheckState = checkState, Size = new Size(40, 24), VisualStylesMode = VisualStylesMode.Net11 @@ -594,7 +595,36 @@ public void CheckBox_ModernGlyph_RendersAccentForCheckedStates(CheckState checkS box.CreateStandardAdapter().PaintUp(e, checkState); - Assert.Equal(expectedAccent, CountPixels(bitmap, Color.Red) > 0); + Color backgroundPixel = bitmap.GetPixel(box.Width - 2, box.Height / 2); + Assert.Equal(Color.Red.ToArgb(), backgroundPixel.ToArgb()); + Assert.Equal( + expectedAccent, + CountPixels(bitmap, Application.SystemVisualSettings.AccentColor) > 0); + } + + [WinFormsFact] + public void CheckBox_ModernGlyph_UsesExplicitBackColorWhenVisualStyleBackgroundDisabled() + { + using Panel parent = new() { BackColor = Color.White }; + using CheckBox box = new() + { + BackColor = Color.Aqua, + CheckState = CheckState.Unchecked, + Text = string.Empty, + Size = new Size(40, 24), + VisualStylesMode = VisualStylesMode.Net11 + }; + + parent.Controls.Add(box); + + using Bitmap bitmap = new(box.Width, box.Height); + using Graphics graphics = Graphics.FromImage(bitmap); + PaintEventArgs e = new(graphics, box.ClientRectangle); + + box.CreateStandardAdapter().PaintUp(e, box.CheckState); + + Color backgroundPixel = bitmap.GetPixel(box.Width - 2, box.Height / 2); + Assert.Equal(Color.Aqua.ToArgb(), backgroundPixel.ToArgb()); } [WinFormsFact] diff --git a/src/test/unit/System.Windows.Forms/System/Windows/Forms/RadioButtonTests.cs b/src/test/unit/System.Windows.Forms/System/Windows/Forms/RadioButtonTests.cs index 8e0b9fc6e02..59aaf621539 100644 --- a/src/test/unit/System.Windows.Forms/System/Windows/Forms/RadioButtonTests.cs +++ b/src/test/unit/System.Windows.Forms/System/Windows/Forms/RadioButtonTests.cs @@ -209,7 +209,7 @@ public void RadioButton_AppearanceChanged_RecreatesModernAdapter() [WinFormsTheory] [InlineData(false, false)] [InlineData(true, true)] - public void RadioButton_ModernGlyph_RendersAccentWhenChecked(bool isChecked, bool expectedAccent) + public void RadioButton_ModernGlyph_UsesExplicitBackColorWithoutTintingCheckedGlyph(bool isChecked, bool expectedAccent) { if (SystemInformation.HighContrast) { @@ -220,6 +220,7 @@ public void RadioButton_ModernGlyph_RendersAccentWhenChecked(bool isChecked, boo using RadioButton control = new() { BackColor = Color.Red, + UseVisualStyleBackColor = true, Checked = isChecked, Size = new Size(40, 24), VisualStylesMode = VisualStylesMode.Net11 @@ -234,7 +235,36 @@ public void RadioButton_ModernGlyph_RendersAccentWhenChecked(bool isChecked, boo e, isChecked ? CheckState.Checked : CheckState.Unchecked); - Assert.Equal(expectedAccent, CountPixels(bitmap, Color.Red) > 0); + Color backgroundPixel = bitmap.GetPixel(control.Width - 2, control.Height / 2); + Assert.Equal(Color.Red.ToArgb(), backgroundPixel.ToArgb()); + Assert.Equal( + expectedAccent, + CountPixels(bitmap, Application.SystemVisualSettings.AccentColor, channelTolerance: 24) > 0); + } + + [WinFormsFact] + public void RadioButton_ModernGlyph_UsesExplicitBackColorWhenVisualStyleBackgroundDisabled() + { + using Panel parent = new() { BackColor = Color.White }; + using RadioButton control = new() + { + BackColor = Color.Aqua, + Checked = false, + Text = string.Empty, + Size = new Size(40, 24), + VisualStylesMode = VisualStylesMode.Net11 + }; + + parent.Controls.Add(control); + + using Bitmap bitmap = new(control.Width, control.Height); + using Graphics graphics = Graphics.FromImage(bitmap); + PaintEventArgs e = new(graphics, control.ClientRectangle); + + control.CreateStandardAdapter().PaintUp(e, CheckState.Unchecked); + + Color backgroundPixel = bitmap.GetPixel(control.Width - 2, control.Height / 2); + Assert.Equal(Color.Aqua.ToArgb(), backgroundPixel.ToArgb()); } [WinFormsFact]