Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2071,6 +2071,15 @@ protected override void ScaleControl(SizeF factor, BoundsSpecified specified)
UpdateFontCache();
}

// In OwnerDrawFixed the native list box doesn't rescale the fixed item height when the control
// autoscales, so scale it here (clamped to [1, 255]; height-axis guard avoids a double-apply). #6382
// Round away from zero: banker's rounding would round .5 midpoints down (15 * 1.5 -> 22), which
// re-introduces the cramped rows this fixes.
if (_drawMode == DrawMode.OwnerDrawFixed && factor.Height != 1F && (specified & BoundsSpecified.Height) != 0)
Comment thread
ricardobossan marked this conversation as resolved.
{
ItemHeight = Math.Clamp((int)Math.Round(_itemHeight * factor.Height, MidpointRounding.AwayFromZero), 1, 255);
}

base.ScaleControl(factor, specified);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1845,6 +1845,76 @@ public void ListBox_ItemHeight_ShouldSerializeValue_Success()
Assert.False(property.ShouldSerializeValue(control));
}

[WinFormsFact]
public void ListBox_ScaleControl_OwnerDrawFixed_ScalesItemHeight()
{
// #6382: an OwnerDrawFixed item height must scale with the control during autoscaling.
using SubListBox control = new() { DrawMode = DrawMode.OwnerDrawFixed, ItemHeight = 20 };

control.ScaleControl(new SizeF(1.5f, 1.5f), BoundsSpecified.All);

Assert.Equal(30, control.ItemHeight);
}

[WinFormsFact]
public void ListBox_ScaleControl_OwnerDrawFixed_WithHandle_UpdatesNativeItemHeight()
{
using SubListBox control = new() { DrawMode = DrawMode.OwnerDrawFixed, ItemHeight = 20 };
Assert.NotEqual(IntPtr.Zero, control.Handle);
Assert.Equal(20, (int)PInvokeCore.SendMessage(control, PInvoke.LB_GETITEMHEIGHT));

control.ScaleControl(new SizeF(2f, 2f), BoundsSpecified.All);

Assert.Equal(40, control.ItemHeight);
Assert.Equal(40, (int)PInvokeCore.SendMessage(control, PInvoke.LB_GETITEMHEIGHT));
}

[WinFormsTheory]
[InlineData(25, 38)] // 37.5 rounds up
[InlineData(15, 23)] // 22.5 rounds up, not down to 22 as banker's rounding would
public void ListBox_ScaleControl_OwnerDrawFixed_RoundsMidpointsAwayFromZero(int itemHeight, int expected)
{
using SubListBox control = new() { DrawMode = DrawMode.OwnerDrawFixed, ItemHeight = itemHeight };

control.ScaleControl(new SizeF(1.5f, 1.5f), BoundsSpecified.All);

Assert.Equal(expected, control.ItemHeight);
}

[WinFormsFact]
public void ListBox_ScaleControl_OwnerDrawFixed_HeightExcluded_DoesNotScaleItemHeight()
{
// A scaling pass that excludes the height axis must leave the item height alone, otherwise the
// included/excluded pass pair in ContainerControl.PerformAutoScale would apply the factor twice.
using SubListBox control = new() { DrawMode = DrawMode.OwnerDrawFixed, ItemHeight = 25 };

control.ScaleControl(new SizeF(1.5f, 1.5f), BoundsSpecified.Width);

Assert.Equal(25, control.ItemHeight);
}

[WinFormsFact]
public void ListBox_ScaleControl_OwnerDrawFixed_ClampsItemHeightToMax()
{
// Scaling must not throw when the result exceeds the 255 maximum; it clamps instead.
using SubListBox control = new() { DrawMode = DrawMode.OwnerDrawFixed, ItemHeight = 200 };

control.ScaleControl(new SizeF(2f, 2f), BoundsSpecified.All);

Assert.Equal(255, control.ItemHeight);
}

[WinFormsFact]
public void ListBox_ScaleControl_Normal_DoesNotChangeItemHeight()
{
using SubListBox control = new() { DrawMode = DrawMode.Normal };
int before = control.ItemHeight;

control.ScaleControl(new SizeF(1.5f, 1.5f), BoundsSpecified.All);

Assert.Equal(before, control.ItemHeight);
}

public static IEnumerable<object[]> Items_CustomCreateItemCollection_TestData()
{
yield return new object[] { null };
Expand Down