Fix ItemHeight of ListBox is not scaled on high DPI in OwnerDrawFixed mode - #14740
Fix ItemHeight of ListBox is not scaled on high DPI in OwnerDrawFixed mode#14740ricardobossan wants to merge 2 commits into
Conversation
An `OwnerDrawFixed` `ListBox` keeps its fixed `ItemHeight` (the reporter's sample sets `25`) when the control is autoscaled. At higher DPI the font grows but the rows stay their design-time height, so the items look cramped. .NET Framework scaled the item height; .NET (Core) doesn't. - Scale the `OwnerDrawFixed` item height by `factor.Height` in `ListBox.ScaleControl`; the same scaling pass that already scales padding and margin. The result is clamped to `[1, 255]`, and a height-axis guard keeps a partial pass from applying the factor twice. - `ScaleControl` is the entry point that both `AutoScaleMode.Font`/`Dpi` and PerMonitorV2 route through, so no per-DPI-message hook is needed. - Owner-draw fixed `ListBox` items are the correct height at higher DPI instead of the design-time height. Long-standing customer report; does not occur on .NET Framework. - Versus .NET Framework: yes (Framework scaled it, Core didn't). Not a recent .NET regression. - Low. Runs only for `OwnerDrawFixed` during a real scaling pass, reuses the `ItemHeight` setter, and clamps so it can't throw. `Normal`/`OwnerDrawVariable` unaffected. Sample is `HighDpiMode.SystemAware` (reads DPI at startup): change the scale, then **relaunch** to 150%: rows stay at `ItemHeight = 25` while the font scales up (cramped). 150%: item height scales (25 > ~38), keeping the 100% proportions. - Unit tests - No accessibility surface change; item height only affects layout. - Windows 11, .NET (main).
Math.Round uses banker's rounding by default, so .5 midpoints could round down (15 * 1.5 -> 22) and re-introduce the cramped rows this fixes. Add tests covering the midpoints (25 -> 38, 15 -> 23) and the height-axis guard that keeps a Height-excluded scaling pass from applying the factor twice.
|
Let's move this to .NET 12 together with the TreeView API we had planned. @bartonjs FYI. |
|
From an API review perspective, no worries, approved is approved... generally things aren't "approved so long as you get them in this version" (OK, sometimes that happens, like adding an |
There was a problem hiding this comment.
Pull request overview
Addresses #6382 by ensuring ListBox.ItemHeight scales appropriately during autoscaling when DrawMode.OwnerDrawFixed is used, matching expected high-DPI behavior and avoiding cramped rows.
Changes:
- Update
ListBox.ScaleControlto scaleOwnerDrawFixedItemHeightbyfactor.Height, guarded against double-application and clamped to[1, 255]. - Use midpoint rounding away from zero to preserve visual proportions at common DPI scale factors.
- Add unit tests covering scaling behavior, native handle synchronization, rounding behavior, exclusion-guard behavior, and clamping.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| src/System.Windows.Forms/System/Windows/Forms/Controls/ListBoxes/ListBox.cs | Scales OwnerDrawFixed ItemHeight during autoscaling with rounding + clamping and a height-axis guard. |
| src/test/unit/System.Windows.Forms/System/Windows/Forms/ListBoxTests.cs | Adds unit test coverage for the new ScaleControl behavior and edge cases. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Fixes #6382
Proposed changes
An
OwnerDrawFixedListBoxkeeps its fixedItemHeight(the reporter's sample sets25) when thecontrol is autoscaled. At higher DPI the font grows but the rows stay their design-time height, so the
items look cramped. .NET Framework scaled the item height; .NET (Core) doesn't.
OwnerDrawFixeditem height byfactor.HeightinListBox.ScaleControl; the samescaling pass that already scales padding and margin. The result is clamped to
[1, 255], and aheight-axis guard keeps a partial pass from applying the factor twice.
ScaleControlis the entry point that bothAutoScaleMode.Font/Dpiand PerMonitorV2 routethrough, so no per-DPI-message hook is needed.
Customer Impact
ListBoxitems are the correct height at higher DPI instead of the design-timeheight. Long-standing customer report; does not occur on .NET Framework.
Regression?
Risk
OwnerDrawFixedduring a real scaling pass, reuses theItemHeightsetter, andclamps so it can't throw.
Normal/OwnerDrawVariableunaffected.Screenshots
Sample is
HighDpiMode.SystemAware(reads DPI at startup): change the scale, then relaunch toBefore
150%: rows stay at
ItemHeight = 25while the font scales up (cramped).After
150%: item height scales (25 > ~38), keeping the 100% proportions.
Test methodology
Accessibility testing
Test environment(s)
Microsoft Reviewers: Open in CodeFlow