|
// 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;
using System.Runtime.InteropServices;
using System.Windows.Forms.Metafiles;
using System.Windows.Forms.VisualStyles;
namespace System.Windows.Forms.Tests;
public class RadioButtonRendererTests : AbstractButtonBaseTests
{
[WinFormsTheory]
[InlineData(RadioButtonState.CheckedNormal)]
[InlineData(RadioButtonState.CheckedPressed)]
public void RadioButtonRenderer_DrawRadioButton(RadioButtonState rBState)
{
using Form form = new Form();
using RadioButton control = (RadioButton)CreateButton();
form.Controls.Add(control);
form.Handle.Should().NotBe(IntPtr.Zero);
using EmfScope emf = new();
DeviceContextState state = new(emf);
using Graphics graphics = Graphics.FromHdc((IntPtr)emf.HDC);
Point point = new(control.Location.X, control.Location.Y);
Rectangle bounds = control.Bounds;
RadioButtonRenderer.DrawRadioButton(graphics, point, rBState);
if (Application.RenderWithVisualStyles)
{
emf.Validate(
state,
Application.RenderWithVisualStyles
? Validate.SkipType(ENHANCED_METAFILE_RECORD_TYPE.EMR_ALPHABLEND)
: Validate.Repeat(Validate.SkipType(ENHANCED_METAFILE_RECORD_TYPE.EMR_STRETCHDIBITS), 1)
);
}
}
[WinFormsTheory]
[InlineData(RadioButtonState.CheckedNormal)]
[InlineData(RadioButtonState.CheckedPressed)]
public void RadioButtonRenderer_DrawRadioButton_OverloadWithSizeAndText(RadioButtonState rBState)
{
using Form form = new Form();
using RadioButton control = (RadioButton)CreateButton();
form.Controls.Add(control);
form.Handle.Should().NotBe(IntPtr.Zero);
using EmfScope emf = new();
DeviceContextState state = new(emf);
using Graphics graphics = Graphics.FromHdc((IntPtr)emf.HDC);
Point point = new(control.Location.X, control.Location.Y);
Rectangle bounds = control.Bounds;
control.Text = "Text";
RadioButtonRenderer.DrawRadioButton(graphics, point, bounds, control.Text, SystemFonts.DefaultFont, false, rBState);
emf.Validate(
state,
Application.RenderWithVisualStyles
? Validate.SkipType(ENHANCED_METAFILE_RECORD_TYPE.EMR_ALPHABLEND)
: Validate.Repeat(Validate.SkipType(ENHANCED_METAFILE_RECORD_TYPE.EMR_STRETCHDIBITS), 1),
Validate.TextOut(
control.Text,
bounds: new Rectangle(41, 5, 20, 12),
State.FontFace(SystemFonts.DefaultFont.Name)
)
);
}
[WinFormsTheory]
[InlineData(TextFormatFlags.Default, RadioButtonState.CheckedNormal)]
[InlineData(TextFormatFlags.Default, RadioButtonState.CheckedPressed)]
[InlineData(TextFormatFlags.PreserveGraphicsTranslateTransform, RadioButtonState.CheckedPressed)]
[InlineData(TextFormatFlags.TextBoxControl, RadioButtonState.UncheckedNormal)]
public void RadioButtonRenderer_DrawRadioButton_OverloadWithTextFormat(TextFormatFlags textFormat,
RadioButtonState rBState)
{
using Form form = new Form();
using RadioButton control = (RadioButton)CreateButton();
form.Controls.Add(control);
form.Handle.Should().NotBe(IntPtr.Zero);
using EmfScope emf = new();
DeviceContextState state = new(emf);
using Graphics graphics = Graphics.FromHdc((IntPtr)emf.HDC);
Point point = new(control.Location.X, control.Location.Y);
Rectangle bounds = control.Bounds;
control.Text = "Text";
RadioButtonRenderer.DrawRadioButton(graphics, point, bounds, control.Text, SystemFonts.DefaultFont, textFormat, false, rBState);
}
[ActiveIssue("https://github.com/dotnet/winforms/issues/12935")]
[WinFormsTheory]
[BoolData]
public void RadioButtonRenderer_DrawRadioButton_OverloadWithHandle(bool focus)
{
// Skip verification of focus = true in X86
// due to the active issue https://github.com/dotnet/winforms/issues/12935
if (RuntimeInformation.ProcessArchitecture == Architecture.X86 && focus)
{
return;
}
using Form form = new Form();
using RadioButton control = (RadioButton)CreateButton();
form.Controls.Add(control);
form.Handle.Should().NotBe(IntPtr.Zero);
using EmfScope emf = new();
DeviceContextState state = new(emf);
using Graphics graphics = Graphics.FromHdc((IntPtr)emf.HDC);
Point point = new(control.Location.X, control.Location.Y);
Rectangle bounds = control.Bounds;
control.Text = "Text";
RadioButtonRenderer.DrawRadioButton(
graphics,
point,
bounds,
control.Text,
SystemFonts.DefaultFont,
TextFormatFlags.Default,
focus,
RadioButtonState.CheckedNormal,
HWND.Null
);
emf.Validate(
state,
Application.RenderWithVisualStyles
? Validate.SkipType(ENHANCED_METAFILE_RECORD_TYPE.EMR_ALPHABLEND)
: Validate.Repeat(Validate.SkipType(ENHANCED_METAFILE_RECORD_TYPE.EMR_STRETCHDIBITS), 1),
Validate.TextOut(
control.Text,
bounds: new Rectangle(3, 0, 20, 12),
State.FontFace(SystemFonts.DefaultFont.Name)
),
(focus
? Validate.PolyPolygon16(new(new(bounds.X, bounds.Y), new Size(-1, -1)))
: null)!,
(focus
? Validate.Repeat(Validate.SkipType(ENHANCED_METAFILE_RECORD_TYPE.EMR_STRETCHDIBITS), 2)
: null)!
);
}
[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;
}
}
[WinFormsTheory]
[BoolData]
public void DrawParentBackground_DoesNotThrow_Or_CallsRenderer(bool renderMatchingApplicationState)
{
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 = renderMatchingApplicationState;
RadioButtonRenderer.DrawParentBackground(g, new Rectangle(0, 0, 10, 10), child);
}
finally
{
RadioButtonRenderer.RenderMatchingApplicationState = original;
}
}
[WinFormsFact]
public void DrawRadioButton_WithImage_Overload_CallsMainOverload()
{
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
);
}
[Theory]
[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);
}
[Theory]
[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();
}
|