You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
TreeView carries a long-standing peculiarity in how the upper/lower margin
between node text and the row edges is calculated — a quirk that
traces back to .NET Framework 2.0 and was ported verbatim into Core. This
proposal aus der Not eine Tugend macht ("turns the necessity into a
virtue"): rather than silently "fix a bug," it productizes the fix as a
first-class, opt-in, designer-visible property — TreeView.NodeLeading
— that
surfaces an existing native TreeView capability
(TVS_NONEVENHEIGHT / TVM_SETITEMHEIGHT) the managed wrapper has never
exposed,
controls backwards compatibility via a sentinel default
(0.0f → legacy path, byte-for-byte unchanged), and
controls the parameter of that capability (the amount of leading
applied to the live Font.Height).
This proposal depends on and references the foundation proposal #14583 — Application.SystemTextSize. Once the system
text-size setting (Settings → Accessibility → Text size; registry HKCU\Software\Microsoft\Accessibility\TextScaleFactor) can change at
runtime, the effective Font.Height can change at runtime — and a
single fixed/cached row-height scalar (today: ItemHeight) is inherently
fragile. NodeLeading is TreeView's specific mechanism for an honest,
text-scale-aware node height.
Why TreeView specifically — the worst-positioned control
Control
Per-item measure hatch?
Native item-height API wrapped?
ListBox / ComboBox
Yes (MeasureItem + OwnerDrawVariable)
ItemHeight exists
ListView (Details)
No
Row height is comctl-computed from SmallImageList + control font
TreeView
No (MeasureItem absent)
Only a single uniform native item height (TVM_SETITEMHEIGHT), with a height-rounding gotcha
TreeView is the only common text-measuring control with neither a
per-item measure hatch nor a clean managed-side knob for the row height
the native control actually uses. Hence the dedicated property.
The legacy calculation — verified against main
Verified against src/System.Windows.Forms/System/Windows/Forms/Controls/TreeView/TreeView.cs
(permalink):
Managed ItemHeight getter without an explicit value returns FontHeight + 3 (or Math.Max(16, FontHeight + 3) for CheckBoxes + OwnerDrawAll), only when the handle has not yet been
created (lines 783–788). Once the handle exists, the getter
delegates to TVM_GETITEMHEIGHT (line 779). So +3/16 are
pre-handle/managed-side estimates, not what the native control
ultimately uses — but they leak into design-time layout and into
any code that queries ItemHeight before realization.
TVM_SETITEMHEIGHT rounds an odd value down to the nearest even
value unless TVS_NONEVENHEIGHT is set — silently eating a
descender pixel for fonts whose natural row height is odd.
WinForms already sets TVS_NONEVENHEIGHT — but only reactively, inside ItemHeight.set when the user assigns an odd
explicit value: _setOddHeight = true → RecreateHandle()
→ TVS_NONEVENHEIGHT flows through CreateParams (lines 51, 369,
801–811). The auto/default, DPI-scaled, non-explicit path never sets TVS_NONEVENHEIGHT — which is exactly the path
that clips at high DPI.
OnHandleCreated pushes _itemHeight only when explicitly set
(line 1916–1919). With no explicit value, comctl picks the
default and the even-floor applies.
The CustomDraw / CDDS_ITEMPREPAINT path carries a long-standing
comment acknowledging that comctl clips node fonts larger than the
control's own font ("better in comctl 5 and above", line 2787–2788). OnHandleCreated conditionally forces CCM_SETVERSION 5 if the current
version is < 5 (lines 1856–1860), which mitigates but does not
fully eliminate the clipping at high DPI.
Precedent for a back-compat switch in this exact area exists: AppContextSwitches.MoveTreeViewTextLocationOnePixel (line 2816).
API Proposal
namespaceSystem.Windows.Forms;publicpartialclassTreeView{/// <summary>/// Gets or sets the per-node vertical leading factor applied on top of/// the live <see cref="Control.Font"/> height. Acts as a sentinel/// switch as well as a scaling factor — see <c>remarks</c>./// </summary>publicfloatNodeLeading{get;set;}/// <summary>/// Occurs when the value of <see cref="NodeLeading"/> changes./// </summary>publiceventEventHandler?NodeLeadingChanged;/// <summary>/// Raises the <see cref="NodeLeadingChanged"/> event./// </summary>protectedvirtualvoidOnNodeLeadingChanged(EventArgse);}
API Usage
// Default behavior (0.0f) — legacy path, no change for existing apps.vartv=newTreeView();Debug.Assert(tv.NodeLeading==0.0f);// Opt in to the honest, font-derived row-height path.tv.NodeLeading=1.0f;// Slightly airier rows (25% extra leading) — uniform for all nodes,// DPI-independent by construction.tv.NodeLeading=1.25f;// React to the change (e.g., from designer/property window) — standard// PropertyChanged pattern.tv.NodeLeadingChanged+=(s,e)=>Trace.WriteLine($"NodeLeading is now {((TreeView)s!).NodeLeading:0.00}");
Sentinel + DPI semantics — the crux
Value
Behavior
0.0f (default)
Sentinel for legacy. Keep the existing FontHeight + 3 managed getter, keep the existing even-rounding behavior, do not set TVS_NONEVENHEIGHT. Existing apps are byte-for-byte unchanged. A zero-height row is mathematically meaningless, which is precisely why 0 is safe as the legacy sentinel.
1.0f
Honest calculation. Derive the base row height from the live Font.Height plus deliberate leading; set TVS_NONEVENHEIGHT so the even-floor cannot eat a descender. Recompute on font change and DPI change.
> 0 and ≠ 1 (e.g. 1.25f)
Scale the leading on top of the honest base (denser/airier rows). Uniform, control-wide multiplier — all that comctl supports.
< 0
ArgumentOutOfRangeException.
DPI behavior — state this explicitly
NodeLeading is a dimensionless factor applied to the live Font.Height,
which is already in device units (it carries the current DPI from the
layout pass). The property is therefore DPI-independent by construction: 1.25 means "+25% leading" identically at 100% and 175%; the pixels
scale with DPI, the factor does not. This is precisely what the legacy +3 constant got wrong — a fixed pixel addend in the wrong unit,
which is why it clips at high DPI.
Implementation constraint — the honest path MUST compute
the row height as (factor × Font.Height)-derived, NOT as Font.Height + N pixels. A pixel addend reintroduces the DPI bug.
Native TreeView item height is uniform — TVM_SETITEMHEIGHT
takes one value for all rows. The property lives on TreeView, not on TreeNode, by design — that placement is itself the signal that it
governs all nodes uniformly. A fractional value does not mean "subdivide
a row" or enable owner-draw "N small rows faked as one tall node." True
per-node heights would need a MeasureItem-style model and effectively a
from-scratch TreeView — out of scope for this proposal.
Naming note — review-negotiable
NodeLeading follows WinForms vocabulary (TreeView has Nodes as ListView has Items), and placement on TreeView conveys the
control-wide scope. Risk: a reader could misread "Node…" as per-node. Recorded so review can decide. Alternatives considered:
ItemLeading — consistent with ItemHeight, but TreeView
uses the term Node elsewhere (Nodes, SelectedNode, TopNode).
Leading — shortest, but ambiguous as a control property name.
Recommendation: NodeLeading, with the per-node misread risk
documented in <remarks> (see XML doc requirements).
Pronunciation/etymology note for international readers (to be embedded in <remarks>): "Leading" (pronounced "ledding") is a typesetting term from
the strips of lead metal once placed between lines of type to add
vertical spacing; it is unrelated to "leading/guiding."
Alternative designs
Expose TVS_NONEVENHEIGHT directly as a bool (e.g. AllowOddItemHeight). Rejected: solves only the rounding gotcha;
does not address the DPI-fragile addend, does not give callers a knob
for denser/airier rows, and adds a second property the user must
understand alongside ItemHeight.
Auto-enable TVS_NONEVENHEIGHT unconditionally in OnHandleCreated.
Rejected: silent behavior change for every existing TreeView — a
rounding shift of 1 pixel will break pixel-perfect screenshot tests and
some custom-drawn UIs. The sentinel-default NodeLeading is opt-in by
construction.
Re-use ItemHeight with a "magic" interpretation
(e.g. 0/-1/float.NaN). Rejected: ItemHeight is an int with a
clear "number of pixels" contract; overloading it with a sentinel is a
worse contract than introducing a small, single-purpose property.
Add MeasureItem to TreeView. Rejected: comctl TreeView has no
variable-row support; faking it would mean re-implementing the control.
See "Explicit non-goal" above.
Risks
Naming-misread risk — NodeLeading could be read as per-node. Mitigated by <remarks> and by placement on TreeView not TreeNode. Review may rename.
Interaction with explicit ItemHeight — precedence rules must
be defined (see Open questions).
Custom-drawn TreeViews — apps that draw at exact pixel
offsets calibrated against the legacy FontHeight + 3 will see different
bounds once they opt in. Default 0.0f keeps them on the legacy path.
Back-compat — the sentinel-0 default is the principal
mitigation. No existing app changes behavior unless it sets NodeLeading.
TVS_NONEVENHEIGHT requires a handle recreate when toggled (today's _setOddHeight path proves this). The honest-path codegen must follow
the same RecreateHandle() pattern, with the standard cost.
Will this feature affect UI controls?
Yes — this is a new property on TreeView.
Designer support: appears in the Properties window. Standard [SRCategory(nameof(SR.CatBehavior))] (or CatAppearance — to be
decided; see existing TreeView property categories for precedent), [SRDescription(...)], [DefaultValue(0.0f)]. CodeDOM serialization
via the ShouldSerializeNodeLeading / ResetNodeLeading pattern from
the new-control-api skill (so the default 0.0f is not emitted into
generated InitializeComponent code).
Localization: N/A for the value. The category/description strings
added to SR.resx follow the existing Cat* / TreeViewOn*Descr
naming conventions and will be .xlf-translated on next build.
XML documentation requirements
<summary> — "Gets or sets the per-node vertical leading
factor applied on top of the live Font.Height. Default 0.0f selects
legacy behavior."
<remarks> — must state explicitly:
Uniform, not per-node.NodeLeading applies uniformly to all
nodes; it is not a per-node knob. Per-node row heights are out of
scope and would require a MeasureItem-style model not supported by
the native TreeView.
Sentinel semantics — 0.0f = legacy
(FontHeight + 3 managed getter, no TVS_NONEVENHEIGHT); 1.0f =
honest, font-derived row height with TVS_NONEVENHEIGHT set; > 1.0f = additional leading on top of the honest base.
DPI behavior — the factor is dimensionless; the resulting
pixels scale with Font.Height, which already carries DPI.
Etymology — "Leading" (pronounced "ledding") is a
typesetting term from the strips of lead metal once placed between
lines of type to add vertical spacing; it is unrelated to
"leading/guiding."
<value> — "A non-negative float. 0.0f (default) selects
legacy behavior. 1.0f opts in to the honest row-height calculation.
Values greater than 1.0f add extra leading."
<exception cref="ArgumentOutOfRangeException"> — thrown when
set to a negative value or to a non-finite value (NaN, ±Infinity).
Serialization:[DefaultValue(0.0f)] plus private bool ShouldSerializeNodeLeading() / private void ResetNodeLeading() so the designer suppresses default
emission.
Open questions for review
Precedence between NodeLeading and an explicit ItemHeight.
Recommended: NodeLeading wins when set to any non-default value
(≠ 0.0f); otherwise ItemHeight behavior is unchanged.
Rationale: once the system text-size can change at runtime ([NET 11 API Proposal] Application.SystemTextSize - runtime awareness of the Accessibility text-scale setting #14583), a
fixed integer ItemHeight is inherently fragile (it does not track
a text-scale change). NodeLeading — a factor on the live Font.Height — is the more robust primary mechanism; ItemHeight becomes the legacy/explicit override that the developer
re-asserts only if they want to pin a pixel value. Alternative: layer NodeLeadingon top ofItemHeight. Flagged for review.
AppContextSwitches gate. Whether the honest-base + TVS_NONEVENHEIGHT path should be additionally gated behind an AppContext switch (precedent: MoveTreeViewTextLocationOnePixel)
for ultra-conservative back-compat. Recommended: no — the
sentinel-0 default already provides full opt-in and makes a second
switch redundant noise.
Re-evaluate on SystemTextSizeChanged ([NET 11 API Proposal] Application.SystemTextSize - runtime awareness of the Accessibility text-scale setting #14583). Whether a NodeLeading != 0.0fTreeView should also recompute its
row-height on the Application / FormSystemTextSizeChanged
notification — so the row height re-flows when the user changes
text size at runtime, not just on font/DPI change. Recommended: yes, conditional on Application.SystemTextSizeAwareness == Notify. The recompute is exactly the same Font.Height × NodeLeading
path; subscribing internally in TreeView.OnHandleCreated (and
unsubscribing in Dispose) is straightforward.
Type: float vs. double. Recommended: float — matches Font.Size, matches WinForms' general "no double in control APIs"
posture, and the precision is more than sufficient for a leading
factor.
Name confirmation.NodeLeading vs. ItemLeading vs. Leading
— see Naming note.
All line numbers below verified against src/System.Windows.Forms/System/Windows/Forms/Controls/TreeView/TreeView.cs
on main at the time of filing; they may drift — re-verify at
implementation time.
Symbol / behavior
Line(s)
_setOddHeight field
51
TVS_NONEVENHEIGHT in CreateParams (gated on _setOddHeight)
Rationale, Background and Motivation
TreeViewcarries a long-standing peculiarity in how the upper/lower marginbetween node text and the row edges is calculated — a quirk that
traces back to .NET Framework 2.0 and was ported verbatim into Core. This
proposal aus der Not eine Tugend macht ("turns the necessity into a
virtue"): rather than silently "fix a bug," it productizes the fix as a
first-class, opt-in, designer-visible property —
TreeView.NodeLeading— that
TreeViewcapability(
TVS_NONEVENHEIGHT/TVM_SETITEMHEIGHT) the managed wrapper has neverexposed,
(
0.0f→ legacy path, byte-for-byte unchanged), andapplied to the live
Font.Height).Why this matters now — companion to #14583
This proposal depends on and references the foundation proposal
#14583 —
Application.SystemTextSize. Once the systemtext-size setting (Settings → Accessibility → Text size; registry
HKCU\Software\Microsoft\Accessibility\TextScaleFactor) can change atruntime, the effective
Font.Heightcan change at runtime — and asingle fixed/cached row-height scalar (today:
ItemHeight) is inherentlyfragile.
NodeLeadingisTreeView's specific mechanism for an honest,text-scale-aware node height.
Why
TreeViewspecifically — the worst-positioned controlListBox/ComboBoxMeasureItem+OwnerDrawVariable)ItemHeightexistsListView(Details)SmallImageList+ control fontTreeViewMeasureItemabsent)TVM_SETITEMHEIGHT), with a height-rounding gotchaTreeViewis the only common text-measuring control with neither aper-item measure hatch nor a clean managed-side knob for the row height
the native control actually uses. Hence the dedicated property.
The legacy calculation — verified against
mainVerified against
src/System.Windows.Forms/System/Windows/Forms/Controls/TreeView/TreeView.cs(permalink):
ItemHeightgetter without an explicit value returnsFontHeight + 3(orMath.Max(16, FontHeight + 3)forCheckBoxes+OwnerDrawAll), only when the handle has not yet beencreated (lines 783–788). Once the handle exists, the getter
delegates to
TVM_GETITEMHEIGHT(line 779). So+3/16arepre-handle/managed-side estimates, not what the native control
ultimately uses — but they leak into design-time layout and into
any code that queries
ItemHeightbefore realization.TVM_SETITEMHEIGHTrounds an odd value down to the nearest evenvalue unless
TVS_NONEVENHEIGHTis set — silently eating adescender pixel for fonts whose natural row height is odd.
TVS_NONEVENHEIGHT— but onlyreactively, inside
ItemHeight.setwhen the user assigns an oddexplicit value:
_setOddHeight = true→RecreateHandle()→
TVS_NONEVENHEIGHTflows throughCreateParams(lines 51, 369,801–811). The auto/default, DPI-scaled, non-explicit path
never sets
TVS_NONEVENHEIGHT— which is exactly the paththat clips at high DPI.
OnHandleCreatedpushes_itemHeightonly when explicitly set(line 1916–1919). With no explicit value, comctl picks the
default and the even-floor applies.
CustomDraw/CDDS_ITEMPREPAINTpath carries a long-standingcomment acknowledging that comctl clips node fonts larger than the
control's own font ("better in comctl 5 and above", line 2787–2788).
OnHandleCreatedconditionally forcesCCM_SETVERSION 5if the currentversion is < 5 (lines 1856–1860), which mitigates but does not
fully eliminate the clipping at high DPI.
AppContextSwitches.MoveTreeViewTextLocationOnePixel(line 2816).API Proposal
API Usage
Sentinel + DPI semantics — the crux
0.0f(default)FontHeight + 3managed getter, keep the existing even-rounding behavior, do not setTVS_NONEVENHEIGHT. Existing apps are byte-for-byte unchanged. A zero-height row is mathematically meaningless, which is precisely why0is safe as the legacy sentinel.1.0fFont.Heightplus deliberate leading; setTVS_NONEVENHEIGHTso the even-floor cannot eat a descender. Recompute on font change and DPI change.> 0and≠ 1(e.g.1.25f)< 0ArgumentOutOfRangeException.DPI behavior — state this explicitly
NodeLeadingis a dimensionless factor applied to the liveFont.Height,which is already in device units (it carries the current DPI from the
layout pass). The property is therefore DPI-independent by construction:
1.25means "+25% leading" identically at 100% and 175%; the pixelsscale with DPI, the factor does not. This is precisely what the legacy
+3constant got wrong — a fixed pixel addend in the wrong unit,which is why it clips at high DPI.
Explicit non-goal — per-node / variable row heights
Native
TreeViewitem height is uniform —TVM_SETITEMHEIGHTtakes one value for all rows. The property lives on
TreeView, not onTreeNode, by design — that placement is itself the signal that itgoverns all nodes uniformly. A fractional value does not mean "subdivide
a row" or enable owner-draw "N small rows faked as one tall node." True
per-node heights would need a
MeasureItem-style model and effectively afrom-scratch
TreeView— out of scope for this proposal.Naming note — review-negotiable
NodeLeadingfollows WinForms vocabulary (TreeViewhas Nodes asListViewhas Items), and placement onTreeViewconveys thecontrol-wide scope. Risk: a reader could misread "Node…" as
per-node. Recorded so review can decide. Alternatives considered:
ItemLeading— consistent withItemHeight, butTreeViewuses the term Node elsewhere (
Nodes,SelectedNode,TopNode).Leading— shortest, but ambiguous as a control property name.Recommendation:
NodeLeading, with the per-node misread riskdocumented in
<remarks>(see XML doc requirements).Alternative designs
TVS_NONEVENHEIGHTdirectly as abool(e.g.AllowOddItemHeight). Rejected: solves only the rounding gotcha;does not address the DPI-fragile addend, does not give callers a knob
for denser/airier rows, and adds a second property the user must
understand alongside
ItemHeight.TVS_NONEVENHEIGHTunconditionally inOnHandleCreated.Rejected: silent behavior change for every existing
TreeView— arounding shift of 1 pixel will break pixel-perfect screenshot tests and
some custom-drawn UIs. The sentinel-default
NodeLeadingis opt-in byconstruction.
ItemHeightwith a "magic" interpretation(e.g.
0/-1/float.NaN). Rejected:ItemHeightis anintwith aclear "number of pixels" contract; overloading it with a sentinel is a
worse contract than introducing a small, single-purpose property.
MeasureItemtoTreeView. Rejected: comctlTreeViewhas novariable-row support; faking it would mean re-implementing the control.
See "Explicit non-goal" above.
Risks
NodeLeadingcould be read asper-node. Mitigated by
<remarks>and by placement onTreeViewnotTreeNode. Review may rename.ItemHeight— precedence rules mustbe defined (see Open questions).
TreeViews — apps that draw at exact pixeloffsets calibrated against the legacy
FontHeight + 3will see differentbounds once they opt in. Default
0.0fkeeps them on the legacy path.0default is the principalmitigation. No existing app changes behavior unless it sets
NodeLeading.TVS_NONEVENHEIGHTrequires a handle recreate when toggled (today's_setOddHeightpath proves this). The honest-path codegen must followthe same
RecreateHandle()pattern, with the standard cost.Will this feature affect UI controls?
Yes — this is a new property on
TreeView.[SRCategory(nameof(SR.CatBehavior))](orCatAppearance— to bedecided; see existing TreeView property categories for precedent),
[SRDescription(...)],[DefaultValue(0.0f)]. CodeDOM serializationvia the
ShouldSerializeNodeLeading/ResetNodeLeadingpattern fromthe new-control-api skill (so the default
0.0fis not emitted intogenerated InitializeComponent code).
half of the runtime text-scale story ([NET 11 API Proposal]
Application.SystemTextSize- runtime awareness of the Accessibility text-scale setting #14583). At high DPI and hightext scale, the honest-path (
NodeLeading >= 1.0f) eliminates thedescender-clipping that today renders some glyphs incomplete for
accessibility-text-size users.
added to
SR.resxfollow the existingCat*/TreeViewOn*Descrnaming conventions and will be
.xlf-translated on next build.XML documentation requirements
<summary>— "Gets or sets the per-node vertical leadingfactor applied on top of the live
Font.Height. Default0.0fselectslegacy behavior."
<remarks>— must state explicitly:NodeLeadingapplies uniformly to allnodes; it is not a per-node knob. Per-node row heights are out of
scope and would require a
MeasureItem-style model not supported bythe native
TreeView.0.0f= legacy(
FontHeight + 3managed getter, noTVS_NONEVENHEIGHT);1.0f=honest, font-derived row height with
TVS_NONEVENHEIGHTset;> 1.0f= additional leading on top of the honest base.pixels scale with
Font.Height, which already carries DPI.typesetting term from the strips of lead metal once placed between
lines of type to add vertical spacing; it is unrelated to
"leading/guiding."
<value>— "A non-negativefloat.0.0f(default) selectslegacy behavior.
1.0fopts in to the honest row-height calculation.Values greater than
1.0fadd extra leading."<exception cref="ArgumentOutOfRangeException">— thrown whenset to a negative value or to a non-finite value (
NaN, ±Infinity).[DefaultValue(0.0f)]plusprivate bool ShouldSerializeNodeLeading()/private void ResetNodeLeading()so the designer suppresses defaultemission.
Open questions for review
NodeLeadingand an explicitItemHeight.Recommended:
NodeLeadingwins when set to any non-default value(
≠ 0.0f); otherwiseItemHeightbehavior is unchanged.Rationale: once the system text-size can change at runtime ([NET 11 API Proposal]
Application.SystemTextSize- runtime awareness of the Accessibility text-scale setting #14583), afixed integer
ItemHeightis inherently fragile (it does not tracka text-scale change).
NodeLeading— a factor on the liveFont.Height— is the more robust primary mechanism;ItemHeightbecomes the legacy/explicit override that the developerre-asserts only if they want to pin a pixel value. Alternative: layer
NodeLeadingon top ofItemHeight. Flagged for review.AppContextSwitchesgate. Whether the honest-base +TVS_NONEVENHEIGHTpath should be additionally gated behind anAppContextswitch (precedent:MoveTreeViewTextLocationOnePixel)for ultra-conservative back-compat. Recommended: no — the
sentinel-
0default already provides full opt-in and makes a secondswitch redundant noise.
SystemTextSizeChanged([NET 11 API Proposal]Application.SystemTextSize- runtime awareness of the Accessibility text-scale setting #14583). Whether aNodeLeading != 0.0fTreeViewshould also recompute itsrow-height on the
Application/FormSystemTextSizeChangednotification — so the row height re-flows when the user changes
text size at runtime, not just on font/DPI change.
Recommended: yes, conditional on
Application.SystemTextSizeAwareness == Notify. The recompute is exactly the sameFont.Height × NodeLeadingpath; subscribing internally in
TreeView.OnHandleCreated(andunsubscribing in
Dispose) is straightforward.floatvs.double. Recommended:float— matchesFont.Size, matches WinForms' general "nodoublein control APIs"posture, and the precision is more than sufficient for a leading
factor.
NodeLeadingvs.ItemLeadingvs.Leading— see Naming note.
Companion proposal
Application.SystemTextSize- runtime awareness of the Accessibility text-scale setting #14583 —Application.SystemTextSize— the foundationproposal this one depends on.
NodeLeadingis the per-control concreteconsumer that motivates the framework-level text-scale awareness; it is
the evidence that the foundation matters.
Source references (verified against
main)All line numbers below verified against
src/System.Windows.Forms/System/Windows/Forms/Controls/TreeView/TreeView.cson
mainat the time of filing; they may drift — re-verify atimplementation time.
_setOddHeightfieldTVS_NONEVENHEIGHTinCreateParams(gated on_setOddHeight)ItemHeightgetter defaultFontHeight + 3/Math.Max(16, FontHeight + 3)ItemHeightsetter — reactive_setOddHeight+RecreateHandle()+TVM_SETITEMHEIGHTCCM_SETVERSION 5inOnHandleCreated(only if version < 5)TVM_SETITEMHEIGHTinOnHandleCreated(only when_itemHeight != -1)CDDS_ITEMPREPAINTcomctl-clipping commentAppContextSwitches.MoveTreeViewTextLocationOnePixelprecedentStatus Checklist
api-suggestionlabelapi-ready-for-reviewblockinglabel to expedite the review appointmentapi-approved