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 6c506d87aaf..749eda02a6a 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 @@ -124,10 +124,10 @@ private void PaintCore(PaintEventArgs e) PaintImage(e, layout); - Color preferredTextColor = Control.ShouldSerializeForeColor() + Color preferredTextColor = Control.ShouldSerializeForeColor() || Control.ForeColor != Forms.Control.DefaultForeColor ? Control.ForeColor : Application.IsDarkModeEnabled - ? Color.FromArgb(0xF0, 0xF0, 0xF0) + ? DarkModeButtonColors.DefaultColors.AcceptButtonTextColor // Use the default accept button text color in dark mode for checkboxes. : SystemColors.WindowText; Color disabledTextBackColor = Control.ShouldSerializeBackColor() && Control.BackColor.A == byte.MaxValue diff --git a/src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/DarkMode/ButtonDarkModeAdapter.cs b/src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/DarkMode/ButtonDarkModeAdapter.cs index 3f9a112accf..c274360bf13 100644 --- a/src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/DarkMode/ButtonDarkModeAdapter.cs +++ b/src/System.Windows.Forms/System/Windows/Forms/Controls/Buttons/ButtonInternal/DarkMode/ButtonDarkModeAdapter.cs @@ -55,7 +55,7 @@ private Color GetButtonTextColor( } bool useEffectiveForeColor = _modern - ? Control.ShouldSerializeForeColor() + ? Control.ShouldSerializeForeColor() || Control.ForeColor != Forms.Control.DefaultForeColor : Control.ForeColor != Forms.Control.DefaultForeColor; if (useEffectiveForeColor) @@ -95,11 +95,11 @@ private Color GetButtonBackColor(PushButtonState state) } else { - bool hasExplicitBackColor = Control.ShouldSerializeBackColor(); - bool hasUsableAmbientBackColor = !Control.BackColor.HasTransparency() - && Control.BackColor != Forms.Control.DefaultBackColor; + bool hasCustomBackColor = _modern + ? Control.ShouldSerializeBackColor() + : Control.BackColor != Forms.Control.DefaultBackColor; - if (hasExplicitBackColor || hasUsableAmbientBackColor) + if (hasCustomBackColor) { backColor = ButtonDarkModeRenderer.GetBackgroundColor( state, 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 412d832507a..2d0aad26122 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 @@ -124,10 +124,10 @@ private void PaintCore(PaintEventArgs e) PaintImage(e, layout); - Color preferredTextColor = Control.ShouldSerializeForeColor() + Color preferredTextColor = Control.ShouldSerializeForeColor() || Control.ForeColor != Forms.Control.DefaultForeColor ? Control.ForeColor : Application.IsDarkModeEnabled - ? Color.FromArgb(0xF0, 0xF0, 0xF0) + ? DarkModeButtonColors.DefaultColors.AcceptButtonTextColor // Use the default accept button text color in dark mode for radio buttons. : SystemColors.WindowText; Color disabledTextBackColor = Control.ShouldSerializeBackColor() && Control.BackColor.A == byte.MaxValue diff --git a/src/System.Windows.Forms/System/Windows/Forms/Rendering/Button/AnimatedPopupButtonRenderer.cs b/src/System.Windows.Forms/System/Windows/Forms/Rendering/Button/AnimatedPopupButtonRenderer.cs index 5a3967073c4..065c2bdb753 100644 --- a/src/System.Windows.Forms/System/Windows/Forms/Rendering/Button/AnimatedPopupButtonRenderer.cs +++ b/src/System.Windows.Forms/System/Windows/Forms/Rendering/Button/AnimatedPopupButtonRenderer.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; @@ -9,7 +9,7 @@ namespace System.Windows.Forms.Rendering.Button; /// -/// Drives and renders a whose is +/// Drives and renders a whose is /// when modern visual styles or dark mode are active, using the concave key-cap /// look of . /// @@ -119,6 +119,7 @@ public override void RenderControl(Graphics graphics) Color faceColor; Color foreColor; Color borderColor; + bool useAutomaticForeColor = false; if (highContrast) { @@ -138,9 +139,8 @@ public override void RenderControl(Graphics graphics) faceColor = PopupButtonColorMath.Blend(baseColor, hoverColor, _hoverCurrent); faceColor = PopupButtonColorMath.Blend(faceColor, pressedColor, _pressCurrent); - bool useAutomaticForeColor = button.EffectiveVisualStylesModeInternal >= VisualStylesMode.Net11 - ? !button.ShouldSerializeForeColor() - : button.ForeColor == Forms.Control.DefaultForeColor; + useAutomaticForeColor = button.ForeColor == Control.DefaultForeColor + && !button.ShouldSerializeForeColor(); foreColor = !useAutomaticForeColor ? button.ForeColor : _baseColorRenderer.GetTextColor(state, button.IsDefault, faceColor); @@ -157,9 +157,7 @@ public override void RenderControl(Graphics graphics) BackColor = faceColor, ForeColor = foreColor, SurfaceColor = button.Parent?.BackColor ?? button.BackColor, - UseAutomaticForeColor = button.EffectiveVisualStylesModeInternal >= VisualStylesMode.Net11 - ? !button.ShouldSerializeForeColor() - : button.ForeColor == Forms.Control.DefaultForeColor, + UseAutomaticForeColor = useAutomaticForeColor, BorderColor = borderColor, BorderWidth = flatAppearance.BorderSize, Enabled = button.Enabled, @@ -233,12 +231,14 @@ public override void RenderControl(Graphics graphics) internal (Color BaseColor, Color HoverColor, Color PressedColor) GetStateColors() { - Forms.ButtonBase button = Button; + ButtonBase button = Button; FlatButtonAppearance flatAppearance = button.FlatAppearance; _baseColorRenderer.DeviceDpi = button.DeviceDpi; _baseColorRenderer.FlatAppearance = flatAppearance; - bool hasCustomBackColor = button.BackColor != Forms.Control.DefaultBackColor; + bool hasCustomBackColor = button.EffectiveVisualStylesModeInternal >= VisualStylesMode.Net11 + ? button.ShouldSerializeBackColor() + : button.BackColor != Control.DefaultBackColor; Color baseColor = hasCustomBackColor ? button.BackColor : _baseColorRenderer.GetBackgroundColor(PushButtonState.Normal, isDefault: false); diff --git a/src/test/unit/System.Windows.Forms/System/Windows/Forms/ButtonVisualStylesTests.cs b/src/test/unit/System.Windows.Forms/System/Windows/Forms/ButtonVisualStylesTests.cs index cbb0ecb7d71..3854f09a295 100644 --- a/src/test/unit/System.Windows.Forms/System/Windows/Forms/ButtonVisualStylesTests.cs +++ b/src/test/unit/System.Windows.Forms/System/Windows/Forms/ButtonVisualStylesTests.cs @@ -814,6 +814,32 @@ public void ButtonDarkModeAdapter_InteractionPaintStateStartsColorAnimation() Assert.True(animator.IsRunning); } + [WinFormsFact] + public void ButtonDarkModeAdapter_InheritedBackColor_UsesThemeStateColorInNet11() + { + using Panel parent = new() { BackColor = Color.Red }; + using Button button = new() + { + FlatStyle = FlatStyle.Standard, + VisualStylesMode = VisualStylesMode.Net11 + }; + parent.Controls.Add(button); + ButtonInternal.ButtonDarkModeAdapter adapter = new(button); + dynamic accessor = adapter.TestAccessor.Dynamic; + ModernButtonDarkModeRenderer neutralRenderer = new() + { + DeviceDpi = button.DeviceDpi, + FlatAppearance = button.FlatAppearance + }; + + Color actual = (Color)accessor.GetButtonBackColor(VisualStyles.PushButtonState.Normal); + + Assert.Equal( + neutralRenderer.GetBackgroundColor(VisualStyles.PushButtonState.Normal, isDefault: false), + actual); + Assert.False(button.ShouldSerializeBackColor()); + } + public static TheoryData ModernImageLayoutData { get @@ -1276,7 +1302,7 @@ public void ButtonDarkModeAdapter_ExplicitForeColor_IsPreserved() } [WinFormsFact] - public void ButtonDarkModeAdapter_InheritedForeColor_UsesAutomaticContrast() + public void ButtonDarkModeAdapter_InheritedForeColor_IsPreservedInNet11() { using Panel parent = new() { ForeColor = Color.Red }; using Button button = new() @@ -1295,7 +1321,7 @@ public void ButtonDarkModeAdapter_InheritedForeColor_UsesAutomaticContrast() VisualStyles.PushButtonState.Normal, Color.White); - Assert.Equal(Color.Black, actual); + Assert.Equal(Color.Red, actual); Assert.False(button.ShouldSerializeForeColor()); } diff --git a/src/test/unit/System.Windows.Forms/System/Windows/Forms/PopupButtonVisualStylesTests.cs b/src/test/unit/System.Windows.Forms/System/Windows/Forms/PopupButtonVisualStylesTests.cs index d12e609f5c0..fb76d383343 100644 --- a/src/test/unit/System.Windows.Forms/System/Windows/Forms/PopupButtonVisualStylesTests.cs +++ b/src/test/unit/System.Windows.Forms/System/Windows/Forms/PopupButtonVisualStylesTests.cs @@ -203,6 +203,37 @@ public void AnimatedPopupButtonRenderer_CustomBackColor_DerivesNeutralStateColor Assert.Equal(PopupButtonColorMath.TowardsContrast(button.BackColor, 0.12f), pressedColor); } + [WinFormsFact] + public void AnimatedPopupButtonRenderer_InheritedBackColor_UsesThemeStateColorsInNet11() + { + using Panel parent = new() { BackColor = Color.Red }; + using Button button = new() + { + FlatStyle = FlatStyle.Popup, + VisualStylesMode = VisualStylesMode.Net11 + }; + parent.Controls.Add(button); + using AnimatedPopupButtonRenderer renderer = new(button); + ModernButtonDarkModeRenderer neutralRenderer = new() + { + DeviceDpi = button.DeviceDpi, + FlatAppearance = button.FlatAppearance + }; + + (Color baseColor, Color hoverColor, Color pressedColor) = renderer.GetStateColors(); + + Assert.Equal( + neutralRenderer.GetBackgroundColor(VisualStyles.PushButtonState.Normal, isDefault: false), + baseColor); + Assert.Equal( + neutralRenderer.GetBackgroundColor(VisualStyles.PushButtonState.Hot, isDefault: false), + hoverColor); + Assert.Equal( + neutralRenderer.GetBackgroundColor(VisualStyles.PushButtonState.Pressed, isDefault: false), + pressedColor); + Assert.False(button.ShouldSerializeBackColor()); + } + [WinFormsFact] public void PopupButtonKeyCapRenderer_FocusedDefault_RendersWithoutThrow() {