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 @@ -25,6 +25,18 @@ protected override unsafe void WndProc(ref Message m)
case PInvokeCore.WM_GETOBJECT:
WmGetObject(ref m);
return;
case PInvokeCore.WM_WINDOWPOSCHANGING:
if (_childWindowType == ChildWindowType.DropDownList)
{
WmWindowPosChanging(ref m);
DefWndProc(ref m);
}
else
{
_owner.ChildWndProc(ref m);
}

break;
Comment on lines +28 to +39
case PInvokeCore.WM_MOUSEMOVE:
if (_childWindowType == ChildWindowType.DropDownList)
{
Expand Down Expand Up @@ -153,5 +165,23 @@ private unsafe void WmGetObject(ref Message m)
throw new InvalidOperationException(SR.RichControlLresult, e);
}
}

private unsafe void WmWindowPosChanging(ref Message m)
{
// The native ComboBox sizes the dropdown list during its own layout
// pass (after CBN_DROPDOWN fires). Intercept here to enforce the
// managed computed height before the OS commits the final size.
// This ensures the UI reflects Items.Count (or explicit DropDownHeight)
// even when the list is empty or items are cleared at runtime.
WINDOWPOS* pos = (WINDOWPOS*)(nint)m.LParamInternal;
if (pos is not null && (pos->flags & SET_WINDOW_POS_FLAGS.SWP_NOSIZE) == 0)
{
int height = _owner.GetCalculatedDropDownHeight();
if (pos->cy != height)
{
pos->cy = height;
}
Comment on lines +177 to +183

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • The WM_WINDOWPOSCHANGING handler unconditionally overrides the dropdown height for every position-change event (as long as SWP_NOSIZE is not set):

     if (pos->cy != height)
     {
         pos->cy = height;
     }
    
    

    This means if the OS intentionally adjusts the dropdown height for legitimate reasons (DPI changes, integral height adjustments, display-edge clamping, or monitor work-area boundaries), the fix will forcefully override it. A safer approach would be to limit the intercept to specific scenarios — e.g., only when the dropdown is initially opening or when items have changed.

  • If the dropdown is near the bottom of the screen, the OS may reduce the dropdown height to fit within the work area. The current fix would override that clamped value back to the full calculated height, potentially causing the dropdown to extend off-screen. The fix should respect pos->cy when it's smaller than the calculated height if the dropdown position is near a screen edge.

}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3327,14 +3327,8 @@ public override string ToString()
return $"{s}, Items.Count: {_itemsCollection?.Count ?? 0}";
}

private void UpdateDropDownHeight()
private int GetCalculatedDropDownHeight()
{
if (_dropDownHandle.IsNull)
{
return;
}

// Now use the DropDownHeight property instead of calculating the Height...
int height = DropDownHeight;
if (height == DefaultDropDownHeight)
{
Expand All @@ -3343,6 +3337,19 @@ private void UpdateDropDownHeight()
height = ItemHeight * count + 2;
}

return height;
}

private void UpdateDropDownHeight()
{
if (_dropDownHandle.IsNull)
{
return;
}

// Now use the DropDownHeight property instead of calculating the Height...
int height = GetCalculatedDropDownHeight();

PInvoke.SetWindowPos(
_dropDownHandle,
HWND.HWND_TOP,
Expand Down
Loading