Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add unit tests for FlatButton, RadioButton, CheckBox, RadioButtonRend…
Browse files Browse the repository at this point in the history
…erer and CheckBoxRenderer
Ricardo Bossan (BEYONDSOFT CONSULTING INC) (from Dev Box) committed Jan 31, 2024
1 parent d152b3c commit 895e1cd
Showing 5 changed files with 596 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -9244,6 +9244,52 @@ public void ButtonBase_WndProc_InvokeSetStateWithHandle_Success(FlatStyle flatSt
Assert.Equal(0, createdCallCount);
}

[WinFormsTheory]
[InlineData(-1)]
[InlineData(0)]
[InlineData(1)]
public unsafe void Button_Flat_ValidBorder(int borderSize)
{
using SubButton button = new()
{
FlatStyle = FlatStyle.Flat,
};

Assert.Throws<NotSupportedException>(() => button.FlatAppearance.BorderColor = Color.Transparent);

if (borderSize < 0)
{
Assert.Throws<ArgumentOutOfRangeException>(() => button.FlatAppearance.BorderSize = borderSize);
}
else
{
button.FlatAppearance.BorderSize = borderSize;
Assert.Equal(borderSize, button.FlatAppearance.BorderSize);
}
}

[WinFormsTheory]
[InlineData(255, 0, 0)]
[InlineData(0, 255, 0)]
[InlineData(0, 0, 255)]
public unsafe void Button_Flat_ProperColor(int red, int green, int blue)
{
Color expectedColor = Color.FromArgb(red, green, blue);

using SubButton button = new()
{
FlatStyle = FlatStyle.Flat,
BackColor = expectedColor
};

button.FlatAppearance.CheckedBackColor = expectedColor;
button.FlatAppearance.BorderColor = expectedColor;

Assert.Equal(expectedColor, button.BackColor);
Assert.Equal(expectedColor, button.FlatAppearance.BorderColor);
Assert.Equal(expectedColor, button.FlatAppearance.CheckedBackColor);
}

private class SubButton : Button
{
public new bool GetStyle(ControlStyles flag) => base.GetStyle(flag);
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
// 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.Windows.Forms.Metafiles;
using System.Windows.Forms.VisualStyles;

namespace System.Windows.Forms.Tests;

public class CheckBoxRenderingTests
{
[WinFormsTheory]
[InlineData(CheckBoxState.CheckedNormal)]
[InlineData(CheckBoxState.MixedNormal)]
public void CheckBoxRenderer_DrawCheckBox(CheckBoxState state)
{
using Bitmap bitmap = new(100, 100);
using Graphics graphics = Graphics.FromImage(bitmap);
Point rectangle = new Point(10, 20);

CheckBoxRenderer.DrawCheckBox(graphics, rectangle, state);
}

[WinFormsTheory]
[InlineData(CheckBoxState.CheckedNormal)]
[InlineData(CheckBoxState.MixedNormal)]
public void CheckBoxRenderer_DrawCheckBox_OverloadWithSizeAndText(CheckBoxState state)
{
using Bitmap bitmap = new(100, 100);
using Graphics graphics = Graphics.FromImage(bitmap);
Point point = new Point(10, 20);
Rectangle bounds = new Rectangle(10, 20, 30, 40);

CheckBoxRenderer.DrawCheckBox(graphics, point, bounds, "Text", SystemFonts.DefaultFont, false, state);
}

[WinFormsTheory]
[InlineData(TextFormatFlags.Default, CheckBoxState.CheckedNormal)]
[InlineData(TextFormatFlags.Default, CheckBoxState.MixedNormal)]
[InlineData(TextFormatFlags.GlyphOverhangPadding, CheckBoxState.MixedHot)]
[InlineData(TextFormatFlags.PreserveGraphicsTranslateTransform, CheckBoxState.CheckedPressed)]
[InlineData(TextFormatFlags.TextBoxControl, CheckBoxState.UncheckedNormal)]
public void CheckBoxRenderer_DrawCheckBox_OverloadWithTextFormat(TextFormatFlags textFormat, CheckBoxState state)
{
using Bitmap bitmap = new(100, 100);
using Graphics graphics = Graphics.FromImage(bitmap);
Point point = new Point(10, 20);
Rectangle bounds = new Rectangle(10, 20, 30, 40);

CheckBoxRenderer.DrawCheckBox(graphics, point, bounds, "Text", SystemFonts.DefaultFont, textFormat, false, state);
}

[WinFormsFact]
public unsafe void CaptureButton()
{
using CheckBox checkBox = new();
using EmfScope emf = new();
checkBox.PrintToMetafile(emf);

List<ENHANCED_METAFILE_RECORD_TYPE> types = [];
List<string> details = [];
emf.Enumerate((ref EmfRecord record) =>
{
types.Add(record.Type);
details.Add(record.ToString());
return true;
});
}

[WinFormsFact]
public unsafe void Button_VisualStyles_off_Default_LineDrawing()
{
if (Application.RenderWithVisualStyles)
{
return;
}

using CheckBox checkBox = new();
using EmfScope emf = new();
DeviceContextState state = new(emf);
Rectangle bounds = checkBox.Bounds;

checkBox.PrintToMetafile(emf);

emf.Validate(
state,
Validate.Repeat(Validate.SkipType(ENHANCED_METAFILE_RECORD_TYPE.EMR_BITBLT), 1),
Validate.LineTo(
new(bounds.Right - 1, 0), new(0, 0),
State.PenColor(SystemColors.ControlLightLight)),
Validate.LineTo(
new(0, 0), new(0, bounds.Bottom - 1),
State.PenColor(SystemColors.ControlLightLight)),
Validate.LineTo(
new(0, bounds.Bottom - 1), new(bounds.Right - 1, bounds.Bottom - 1),
State.PenColor(SystemColors.ControlDarkDark)),
Validate.LineTo(
new(bounds.Right - 1, bounds.Bottom - 1), new(bounds.Right - 1, -1),
State.PenColor(SystemColors.ControlDarkDark)),
Validate.LineTo(
new(bounds.Right - 2, 1), new(1, 1),
State.PenColor(SystemColors.Control)),
Validate.LineTo(
new(1, 1), new(1, bounds.Bottom - 2),
State.PenColor(SystemColors.Control)),
Validate.LineTo(
new(1, bounds.Bottom - 2), new(bounds.Right - 2, bounds.Bottom - 2),
State.PenColor(SystemColors.ControlDark)),
Validate.LineTo(
new(bounds.Right - 2, bounds.Bottom - 2), new(bounds.Right - 2, 0),
State.PenColor(SystemColors.ControlDark)));
}

[WinFormsFact]
public unsafe void Button_VisualStyles_off_Default_WithText_LineDrawing()
{
if (Application.RenderWithVisualStyles)
{
return;
}

using CheckBox checkBox = new() { Text = "Hello" };
using EmfScope emf = new();
DeviceContextState state = new(emf);
Rectangle bounds = checkBox.Bounds;

checkBox.PrintToMetafile(emf);

emf.Validate(
state,
Validate.SkipType(ENHANCED_METAFILE_RECORD_TYPE.EMR_BITBLT),
Validate.TextOut("Hello"),
Validate.LineTo(
new(bounds.Right - 1, 0), new(0, 0),
State.PenColor(SystemColors.ControlLightLight)),
Validate.LineTo(
new(0, 0), new(0, bounds.Bottom - 1),
State.PenColor(SystemColors.ControlLightLight)),
Validate.LineTo(
new(0, bounds.Bottom - 1), new(bounds.Right - 1, bounds.Bottom - 1),
State.PenColor(SystemColors.ControlDarkDark)),
Validate.LineTo(
new(bounds.Right - 1, bounds.Bottom - 1), new(bounds.Right - 1, -1),
State.PenColor(SystemColors.ControlDarkDark)),
Validate.LineTo(
new(bounds.Right - 2, 1), new(1, 1),
State.PenColor(SystemColors.Control)),
Validate.LineTo(
new(1, 1), new(1, bounds.Bottom - 2),
State.PenColor(SystemColors.Control)),
Validate.LineTo(
new(1, bounds.Bottom - 2), new(bounds.Right - 2, bounds.Bottom - 2),
State.PenColor(SystemColors.ControlDark)),
Validate.LineTo(
new(bounds.Right - 2, bounds.Bottom - 2), new(bounds.Right - 2, 0),
State.PenColor(SystemColors.ControlDark)));
}

[WinFormsFact]
public unsafe void CaptureButtonOnForm()
{
using Form form = new();
using CheckBox checkBox = new();
form.Controls.Add(checkBox);

using EmfScope emf = new();
form.PrintToMetafile(emf);

string details = emf.RecordsToString();
}
}
Original file line number Diff line number Diff line change
@@ -493,6 +493,9 @@ public class SubCheckBox : CheckBox
public new bool GetTopLevel() => base.GetTopLevel();

public new void OnClick(EventArgs e) => base.OnClick(e);
public new void OnMouseUp(MouseEventArgs e) => base.OnMouseUp(e);
internal new void OnMouseClick(MouseEventArgs e) => base.OnMouseClick(e);
internal new void OnMouseDown(MouseEventArgs e) => base.OnMouseDown(e);
}

private class TestCheckBox : CheckBox
@@ -527,4 +530,162 @@ internal override bool RaiseAutomationPropertyChangedEvent(UIA_PROPERTY_ID prope
return base.RaiseAutomationPropertyChangedEvent(propertyId, oldValue, newValue);
}
}

[WinFormsFact]
public void CheckBox_CheckedChangedEvent_Fires()
{
CheckBox checkBox = new CheckBox();
bool eventFired = false;

checkBox.CheckedChanged += (sender, args) => eventFired = true;
checkBox.Checked = !checkBox.Checked;

Assert.True(eventFired);
}

[WinFormsFact]
public void CheckBox_CheckStateChangedEvent_Fires()
{
CheckBox checkBox = new CheckBox();
bool eventFired = false;

checkBox.CheckStateChanged += (sender, args) => eventFired = true;
checkBox.CheckState = checkBox.CheckState == CheckState.Checked ? CheckState.Unchecked : CheckState.Checked;

Assert.True(eventFired);
}

[WinFormsTheory]
[InlineData(Appearance.Button, FlatStyle.Standard)]
[InlineData(Appearance.Button, FlatStyle.Flat)]
[InlineData(Appearance.Button, FlatStyle.Popup)]
[InlineData(Appearance.Button, FlatStyle.System)]
[InlineData(Appearance.Normal, FlatStyle.Standard)]
[InlineData(Appearance.Normal, FlatStyle.Flat)]
[InlineData(Appearance.Normal, FlatStyle.Popup)]
[InlineData(Appearance.Normal, FlatStyle.System)]
public void CheckBox_OverChangeRectangle_ReturnsExpectedRectangle(Appearance appearance, FlatStyle flatStyle)
{
SubCheckBox checkBox = new SubCheckBox()
{
Appearance = appearance,
FlatStyle = flatStyle
};

Rectangle overChangeRectangle = new();
// ButtonBase.Adapter prohibits this
if (appearance == Appearance.Normal && (flatStyle != FlatStyle.Standard && flatStyle != FlatStyle.Popup && flatStyle != FlatStyle.Flat))
{
Assert.ThrowsAny<Exception>(() => overChangeRectangle = checkBox.OverChangeRectangle);

return;
}
else
{
overChangeRectangle = checkBox.OverChangeRectangle;
}

if (appearance == Appearance.Button)
{
if (flatStyle == FlatStyle.Standard)
Assert.Equal(new Rectangle(-1, -1, 1, 1), overChangeRectangle);
else
{
Assert.Equal(checkBox.ClientRectangle, overChangeRectangle);
}
}
else if (flatStyle == FlatStyle.Standard)
{
Assert.Equal(new Rectangle(-1, -1, 1, 1), overChangeRectangle);
}
else
{
Assert.Equal(checkBox.Adapter.CommonLayout().Layout().CheckBounds, overChangeRectangle);
}
}

[WinFormsTheory]
[InlineData(Appearance.Button, FlatStyle.Standard)]
[InlineData(Appearance.Button, FlatStyle.Flat)]
[InlineData(Appearance.Button, FlatStyle.Popup)]
[InlineData(Appearance.Button, FlatStyle.System)]
[InlineData(Appearance.Normal, FlatStyle.Standard)]
[InlineData(Appearance.Normal, FlatStyle.Flat)]
[InlineData(Appearance.Normal, FlatStyle.Popup)]
[InlineData(Appearance.Normal, FlatStyle.System)]
public void CheckBox_DownChangeRectangle_ReturnsExpectedRectangle(Appearance appearance, FlatStyle flatStyle)
{
SubCheckBox checkBox = new SubCheckBox()
{
Appearance = appearance,
FlatStyle = flatStyle
};

Rectangle downChangeRectangle = checkBox.DownChangeRectangle;

if (appearance == Appearance.Button || flatStyle == FlatStyle.System)
{
Assert.Equal(checkBox.ClientRectangle, downChangeRectangle);
}
else
{
Assert.Equal(checkBox.Adapter.CommonLayout().Layout().CheckBounds, downChangeRectangle);
}
}

[WinFormsTheory]
[InlineData(true)]
[InlineData(false)]
public void CheckBox_LeftClick_MouseUpCounts(bool capture)
{
Form form = new();
SubCheckBox control = new() { Capture = capture };
form.Controls.Add(control);
control.TabIndex = 9999;
form.Show();

MouseEventArgs eventArgs = new MouseEventArgs(MouseButtons.Left, 1, new Point(0, 0), 0);

int callCountOnMouseUp = 0;

control.MouseUp += (sender, e) =>
{
Assert.Same(control, sender);
Assert.Same(eventArgs, e);
callCountOnMouseUp++;
};

control.OnMouseUp(eventArgs);
Assert.True(callCountOnMouseUp == 1);
}

[WinFormsTheory]
[InlineData(true, '&', "&MnemonicText")]
[InlineData(true, 'N', "NonMnemonicText")]
[InlineData(true, 'M', "&MnemonicText")]
[InlineData(false, 'M', "&MnemonicText")]
public void CheckBox_ProcessMnemonic_ValidCases(bool useMnemonic, char charCode, string buttonText)
{
Form form = new();
using SubCheckBox checkBox = new()
{
UseMnemonic = useMnemonic,
Text = buttonText,
};
form.Controls.Add(checkBox);
form.Show();

bool result = checkBox.ProcessMnemonic(charCode);

if (useMnemonic && charCode != '&' && buttonText.Contains($"&{charCode}", StringComparison.OrdinalIgnoreCase))
{
Assert.True(result);

Assert.True(checkBox.Focused);
}
else
{
Assert.False(result);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
// 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.Windows.Forms.Metafiles;
using System.Windows.Forms.VisualStyles;

namespace System.Windows.Forms.Tests;

public class RadioButtonRenderingTests
{
[WinFormsTheory]
[InlineData(RadioButtonState.CheckedNormal)]
[InlineData(RadioButtonState.CheckedPressed)]
public void RadioButtonRenderer_DrawRadioButton(RadioButtonState state)
{
using Bitmap bitmap = new(100, 100);
using Graphics graphics = Graphics.FromImage(bitmap);
Point rectangle = new Point(10, 20);

RadioButtonRenderer.DrawRadioButton(graphics, rectangle, state);
}

[WinFormsTheory]
[InlineData(RadioButtonState.CheckedNormal)]
[InlineData(RadioButtonState.CheckedPressed)]
public void RadioButtonRenderer_DrawRadioButton_OverloadWithSizeAndText(RadioButtonState state)
{
using Bitmap bitmap = new(100, 100);
using Graphics graphics = Graphics.FromImage(bitmap);
Point point = new Point(10, 20);
Rectangle bounds = new Rectangle(10, 20, 30, 40);

RadioButtonRenderer.DrawRadioButton(graphics, point, bounds, "Text", SystemFonts.DefaultFont, false, state);
}

[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 state)
{
using Bitmap bitmap = new(100, 100);
using Graphics graphics = Graphics.FromImage(bitmap);
Point point = new Point(10, 20);
Rectangle bounds = new Rectangle(10, 20, 30, 40);

RadioButtonRenderer.DrawRadioButton(graphics, point, bounds, "Text", SystemFonts.DefaultFont, textFormat, false, state);
}

[WinFormsFact]
public unsafe void CaptureButton()
{
using RadioButton RadioButton = new();
using EmfScope emf = new();
RadioButton.PrintToMetafile(emf);

List<ENHANCED_METAFILE_RECORD_TYPE> types = [];
List<string> details = [];
emf.Enumerate((ref EmfRecord record) =>
{
types.Add(record.Type);
details.Add(record.ToString());
return true;
});
}

[WinFormsFact]
public unsafe void Button_VisualStyles_off_Default_LineDrawing()
{
if (Application.RenderWithVisualStyles)
{
return;
}

using RadioButton RadioButton = new();
using EmfScope emf = new();
DeviceContextState state = new(emf);
Rectangle bounds = RadioButton.Bounds;

RadioButton.PrintToMetafile(emf);

emf.Validate(
state,
Validate.Repeat(Validate.SkipType(ENHANCED_METAFILE_RECORD_TYPE.EMR_BITBLT), 1),
Validate.LineTo(
new(bounds.Right - 1, 0), new(0, 0),
State.PenColor(SystemColors.ControlLightLight)),
Validate.LineTo(
new(0, 0), new(0, bounds.Bottom - 1),
State.PenColor(SystemColors.ControlLightLight)),
Validate.LineTo(
new(0, bounds.Bottom - 1), new(bounds.Right - 1, bounds.Bottom - 1),
State.PenColor(SystemColors.ControlDarkDark)),
Validate.LineTo(
new(bounds.Right - 1, bounds.Bottom - 1), new(bounds.Right - 1, -1),
State.PenColor(SystemColors.ControlDarkDark)),
Validate.LineTo(
new(bounds.Right - 2, 1), new(1, 1),
State.PenColor(SystemColors.Control)),
Validate.LineTo(
new(1, 1), new(1, bounds.Bottom - 2),
State.PenColor(SystemColors.Control)),
Validate.LineTo(
new(1, bounds.Bottom - 2), new(bounds.Right - 2, bounds.Bottom - 2),
State.PenColor(SystemColors.ControlDark)),
Validate.LineTo(
new(bounds.Right - 2, bounds.Bottom - 2), new(bounds.Right - 2, 0),
State.PenColor(SystemColors.ControlDark)));
}

[WinFormsFact]
public unsafe void Button_VisualStyles_off_Default_WithText_LineDrawing()
{
if (Application.RenderWithVisualStyles)
{
return;
}

using RadioButton RadioButton = new() { Text = "Hello" };
using EmfScope emf = new();
DeviceContextState state = new(emf);
Rectangle bounds = RadioButton.Bounds;

RadioButton.PrintToMetafile(emf);

emf.Validate(
state,
Validate.SkipType(ENHANCED_METAFILE_RECORD_TYPE.EMR_BITBLT),
Validate.TextOut("Hello"),
Validate.LineTo(
new(bounds.Right - 1, 0), new(0, 0),
State.PenColor(SystemColors.ControlLightLight)),
Validate.LineTo(
new(0, 0), new(0, bounds.Bottom - 1),
State.PenColor(SystemColors.ControlLightLight)),
Validate.LineTo(
new(0, bounds.Bottom - 1), new(bounds.Right - 1, bounds.Bottom - 1),
State.PenColor(SystemColors.ControlDarkDark)),
Validate.LineTo(
new(bounds.Right - 1, bounds.Bottom - 1), new(bounds.Right - 1, -1),
State.PenColor(SystemColors.ControlDarkDark)),
Validate.LineTo(
new(bounds.Right - 2, 1), new(1, 1),
State.PenColor(SystemColors.Control)),
Validate.LineTo(
new(1, 1), new(1, bounds.Bottom - 2),
State.PenColor(SystemColors.Control)),
Validate.LineTo(
new(1, bounds.Bottom - 2), new(bounds.Right - 2, bounds.Bottom - 2),
State.PenColor(SystemColors.ControlDark)),
Validate.LineTo(
new(bounds.Right - 2, bounds.Bottom - 2), new(bounds.Right - 2, 0),
State.PenColor(SystemColors.ControlDark)));
}

[WinFormsFact]
public unsafe void CaptureButtonOnForm()
{
using Form form = new();
using RadioButton RadioButton = new();
form.Controls.Add(RadioButton);

using EmfScope emf = new();
form.PrintToMetafile(emf);

string details = emf.RecordsToString();
}
}
Original file line number Diff line number Diff line change
@@ -1625,4 +1625,52 @@ internal override bool RaiseAutomationPropertyChangedEvent(UIA_PROPERTY_ID prope
return base.RaiseAutomationPropertyChangedEvent(propertyId, oldValue, newValue);
}
}

[WinFormsTheory]
[InlineData(Appearance.Button, FlatStyle.Standard)]
[InlineData(Appearance.Button, FlatStyle.Flat)]
[InlineData(Appearance.Button, FlatStyle.Popup)]
[InlineData(Appearance.Button, FlatStyle.System)]
[InlineData(Appearance.Normal, FlatStyle.Standard)]
[InlineData(Appearance.Normal, FlatStyle.Flat)]
[InlineData(Appearance.Normal, FlatStyle.Popup)]
[InlineData(Appearance.Normal, FlatStyle.System)]
public void RadioButton_OverChangeRectangle_Get(Appearance appearance, FlatStyle flatStyle)
{
SubRadioButton control = new()
{
Appearance = appearance,
FlatStyle = flatStyle
};

Rectangle overChangeRectangle = new();
// ButtonBase.Adapter prohibits this
if (appearance == Appearance.Normal && (flatStyle != FlatStyle.Standard && flatStyle != FlatStyle.Popup && flatStyle != FlatStyle.Flat))
{
Assert.ThrowsAny<Exception>(() => overChangeRectangle = control.OverChangeRectangle);

return;
}
else
{
overChangeRectangle = control.OverChangeRectangle;
}

if (control.FlatStyle == FlatStyle.Standard)
{
Assert.True(overChangeRectangle == new Rectangle(-1, -1, 1, 1));
}

if (control.Appearance == Appearance.Button)
{
if (control.FlatStyle != FlatStyle.Standard)
{
Assert.True(overChangeRectangle == control.ClientRectangle);
}
}
else if (control.FlatStyle != FlatStyle.Standard)
{
Assert.True(overChangeRectangle == control.Adapter.CommonLayout().Layout().CheckBounds);
}
}
}

0 comments on commit 895e1cd

Please sign in to comment.