From b56856f7f8a2683149fffb9cc127b24e405db712 Mon Sep 17 00:00:00 2001 From: "Zheng Li (BEYONDSOFT CONSULTING INC)" Date: Tue, 13 May 2025 16:06:48 +0800 Subject: [PATCH 1/2] Add code coverage for RadioButtonRenderer --- .../Windows/Forms/RadioButtonRendererTests.cs | 231 +++++++++++++++++- 1 file changed, 229 insertions(+), 2 deletions(-) diff --git a/src/test/unit/System.Windows.Forms/System/Windows/Forms/RadioButtonRendererTests.cs b/src/test/unit/System.Windows.Forms/System/Windows/Forms/RadioButtonRendererTests.cs index 5d210e9fb1d..fa56fbad241 100644 --- a/src/test/unit/System.Windows.Forms/System/Windows/Forms/RadioButtonRendererTests.cs +++ b/src/test/unit/System.Windows.Forms/System/Windows/Forms/RadioButtonRendererTests.cs @@ -1,8 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#nullable disable - using System.Drawing; using System.Runtime.InteropServices; using System.Windows.Forms.Metafiles; @@ -157,5 +155,234 @@ public void RadioButtonRenderer_DrawRadioButton_OverloadWithHandle(bool focus) ); } + [WinFormsTheory] + [InlineData(RadioButtonState.CheckedNormal)] + [InlineData(RadioButtonState.CheckedPressed)] + [InlineData(RadioButtonState.CheckedDisabled)] + [InlineData(RadioButtonState.UncheckedNormal)] + [InlineData(RadioButtonState.UncheckedPressed)] + [InlineData(RadioButtonState.UncheckedDisabled)] + public void IsBackgroundPartiallyTransparent_ReturnsExpected(RadioButtonState state) + { + bool original = RadioButtonRenderer.RenderMatchingApplicationState; + + try + { + RadioButtonRenderer.RenderMatchingApplicationState = false; + bool resultWithVisualStyles = RadioButtonRenderer.IsBackgroundPartiallyTransparent(state); + + RadioButtonRenderer.RenderMatchingApplicationState = true; + bool resultWithoutVisualStyles = RadioButtonRenderer.IsBackgroundPartiallyTransparent(state); + + if (Application.RenderWithVisualStyles) + { + resultWithVisualStyles.Should().BeTrue(); + } + else + { + resultWithVisualStyles.Should().BeFalse(); + } + + if (!Application.RenderWithVisualStyles) + { + resultWithoutVisualStyles.Should().BeFalse(); + } + } + finally + { + RadioButtonRenderer.RenderMatchingApplicationState = original; + } + } + + [WinFormsFact] + public void DrawParentBackground_DoesNotThrow_WhenVisualStylesDisabled() + { + using Form parent = new(); + using Panel child = new(); + parent.Controls.Add(child); + parent.Show(); + + using Bitmap bmp = new(10, 10); + using Graphics g = Graphics.FromImage(bmp); + + bool original = RadioButtonRenderer.RenderMatchingApplicationState; + try + { + RadioButtonRenderer.RenderMatchingApplicationState = true; + RadioButtonRenderer.DrawParentBackground(g, new Rectangle(0, 0, 10, 10), child); + } + finally + { + RadioButtonRenderer.RenderMatchingApplicationState = original; + } + } + + [WinFormsFact] + public void DrawParentBackground_CallsRenderer_WhenVisualStylesEnabled() + { + using Form parent = new(); + using Panel child = new(); + parent.Controls.Add(child); + parent.Show(); + + using Bitmap bmp = new(10, 10); + using Graphics g = Graphics.FromImage(bmp); + + bool original = RadioButtonRenderer.RenderMatchingApplicationState; + try + { + RadioButtonRenderer.RenderMatchingApplicationState = false; + RadioButtonRenderer.DrawParentBackground(g, new Rectangle(0, 0, 10, 10), child); + } + finally + { + RadioButtonRenderer.RenderMatchingApplicationState = original; + } + } + + [WinFormsFact] + public void DrawRadioButton_WithImage_Overload_CallsMainOverload() + { + using Form form = new(); + using RadioButton control = (RadioButton)CreateButton(); + form.Controls.Add(control); + form.Show(); + + using Bitmap bmp = new(20, 20); + using Graphics g = Graphics.FromImage(bmp); + using Image image = new Bitmap(10, 10); + + Point glyphLocation = new(2, 2); + Rectangle textBounds = new(5, 5, 30, 15); + Rectangle imageBounds = new(7, 7, 10, 10); + string radioButtonText = "Radio"; + Font font = SystemFonts.DefaultFont; + bool focused = false; + RadioButtonState state = RadioButtonState.CheckedNormal; + + RadioButtonRenderer.DrawRadioButton( + g, + glyphLocation, + textBounds, + radioButtonText, + font, + image, + imageBounds, + focused, + state + ); + } + + [WinFormsFact] + public void DrawRadioButton_WithImage_Overload_AllowsNullTextAndFont() + { + using Bitmap bmp = new(20, 20); + using Graphics g = Graphics.FromImage(bmp); + using Image image = new Bitmap(10, 10); + + Point glyphLocation = new(0, 0); + Rectangle textBounds = new(0, 0, 10, 10); + Rectangle imageBounds = new(0, 0, 10, 10); + bool focused = false; + RadioButtonState state = RadioButtonState.UncheckedNormal; + + RadioButtonRenderer.DrawRadioButton( + g, + glyphLocation, + textBounds, + null, + null, + image, + imageBounds, + focused, + state + ); + } + + [WinFormsTheory] + [InlineData(RadioButtonState.CheckedNormal)] + [InlineData(RadioButtonState.CheckedPressed)] + [InlineData(RadioButtonState.UncheckedNormal)] + [InlineData(RadioButtonState.UncheckedPressed)] + public void GetGlyphSize_ReturnsExpectedSize(RadioButtonState state) + { + using Bitmap bmp = new(20, 20); + using Graphics g = Graphics.FromImage(bmp); + + Size size = RadioButtonRenderer.GetGlyphSize(g, state); + + if (Application.RenderWithVisualStyles) + { + size.Width.Should().BeGreaterThan(0); + size.Height.Should().BeGreaterThan(0); + } + else + { + size.Should().Be(new Size(13, 13)); + } + } + + [WinFormsFact] + public void DrawRadioButton_Internal_WithImageAndText_DoesNotThrow() + { + using Bitmap bmp = new(30, 30); + using Graphics g = Graphics.FromImage(bmp); + using Image image = new Bitmap(10, 10); + + Point glyphLocation = new(1, 1); + Rectangle textBounds = new(12, 1, 15, 15); + Rectangle imageBounds = new(2, 2, 10, 10); + string radioButtonText = "Test"; + Font font = SystemFonts.DefaultFont; + TextFormatFlags flags = TextFormatFlags.Default; + bool focused = true; + RadioButtonState state = RadioButtonState.CheckedNormal; + HWND hwnd = HWND.Null; + + typeof(RadioButtonRenderer) + .TestAccessor() + .Dynamic + .DrawRadioButton( + g, + glyphLocation, + textBounds, + radioButtonText, + font, + flags, + image, + imageBounds, + focused, + state, + hwnd + ); + } + + [WinFormsTheory] + [InlineData(RadioButtonState.CheckedNormal, ButtonState.Checked)] + [InlineData(RadioButtonState.CheckedHot, ButtonState.Checked)] + [InlineData(RadioButtonState.CheckedPressed, ButtonState.Checked | ButtonState.Pushed)] + [InlineData(RadioButtonState.CheckedDisabled, ButtonState.Checked | ButtonState.Inactive)] + [InlineData(RadioButtonState.UncheckedPressed, ButtonState.Pushed)] + [InlineData(RadioButtonState.UncheckedDisabled, ButtonState.Inactive)] + [InlineData(RadioButtonState.UncheckedNormal, ButtonState.Normal)] + public void ConvertToButtonState_ReturnsExpected(RadioButtonState radioState, ButtonState expected) + { + RadioButtonRenderer.ConvertToButtonState(radioState).Should().Be(expected); + } + + [WinFormsTheory] + [InlineData(ButtonState.Checked, false, RadioButtonState.CheckedNormal)] + [InlineData(ButtonState.Checked, true, RadioButtonState.CheckedHot)] + [InlineData(ButtonState.Checked | ButtonState.Pushed, false, RadioButtonState.CheckedPressed)] + [InlineData(ButtonState.Checked | ButtonState.Inactive, false, RadioButtonState.CheckedDisabled)] + [InlineData(ButtonState.Pushed, false, RadioButtonState.UncheckedPressed)] + [InlineData(ButtonState.Inactive, false, RadioButtonState.UncheckedDisabled)] + [InlineData(ButtonState.Normal, false, RadioButtonState.UncheckedNormal)] + [InlineData(ButtonState.Normal, true, RadioButtonState.UncheckedHot)] + public void ConvertFromButtonState_ReturnsExpected(ButtonState buttonState, bool isHot, RadioButtonState expected) + { + RadioButtonRenderer.ConvertFromButtonState(buttonState, isHot).Should().Be(expected); + } + protected override ButtonBase CreateButton() => new RadioButton(); } From 3f017bcc9241540ee7d3580f383ea5b6d83dd8f2 Mon Sep 17 00:00:00 2001 From: "Zheng Li (BEYONDSOFT CONSULTING INC)" Date: Thu, 15 May 2025 09:25:08 +0800 Subject: [PATCH 2/2] Address FeedBacks --- .../System/Windows/Forms/RadioButtonRendererTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/unit/System.Windows.Forms/System/Windows/Forms/RadioButtonRendererTests.cs b/src/test/unit/System.Windows.Forms/System/Windows/Forms/RadioButtonRendererTests.cs index fa56fbad241..32ae3f4b964 100644 --- a/src/test/unit/System.Windows.Forms/System/Windows/Forms/RadioButtonRendererTests.cs +++ b/src/test/unit/System.Windows.Forms/System/Windows/Forms/RadioButtonRendererTests.cs @@ -357,7 +357,7 @@ public void DrawRadioButton_Internal_WithImageAndText_DoesNotThrow() ); } - [WinFormsTheory] + [Theory] [InlineData(RadioButtonState.CheckedNormal, ButtonState.Checked)] [InlineData(RadioButtonState.CheckedHot, ButtonState.Checked)] [InlineData(RadioButtonState.CheckedPressed, ButtonState.Checked | ButtonState.Pushed)] @@ -370,7 +370,7 @@ public void ConvertToButtonState_ReturnsExpected(RadioButtonState radioState, Bu RadioButtonRenderer.ConvertToButtonState(radioState).Should().Be(expected); } - [WinFormsTheory] + [Theory] [InlineData(ButtonState.Checked, false, RadioButtonState.CheckedNormal)] [InlineData(ButtonState.Checked, true, RadioButtonState.CheckedHot)] [InlineData(ButtonState.Checked | ButtonState.Pushed, false, RadioButtonState.CheckedPressed)]