From 4f4549cac4bcc2f395ad09191231c54975e6cf60 Mon Sep 17 00:00:00 2001 From: JayashreeSF3546 Date: Thu, 4 Jun 2026 16:01:50 +0530 Subject: [PATCH 1/6] 339 The height of the "DropDown" list for the combobox control can't be reset default height after clear the combobox items. --- .../ComboBox.ComboBoxChildNativeWindow.cs | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/System.Windows.Forms/System/Windows/Forms/Controls/ComboBox/ComboBox.ComboBoxChildNativeWindow.cs b/src/System.Windows.Forms/System/Windows/Forms/Controls/ComboBox/ComboBox.ComboBoxChildNativeWindow.cs index 60b17e60db7..61544466151 100644 --- a/src/System.Windows.Forms/System/Windows/Forms/Controls/ComboBox/ComboBox.ComboBoxChildNativeWindow.cs +++ b/src/System.Windows.Forms/System/Windows/Forms/Controls/ComboBox/ComboBox.ComboBoxChildNativeWindow.cs @@ -24,6 +24,26 @@ protected override unsafe void WndProc(ref Message m) { case PInvokeCore.WM_GETOBJECT: WmGetObject(ref m); + return; + case PInvokeCore.WM_WINDOWPOSCHANGING: + if (_childWindowType == ChildWindowType.DropDownList) + { + // 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) + { + var height = _owner.GetCalculatedDropDownHeight(); + if (pos->cy != height) + { + pos->cy = height; + } + } + } + return; case PInvokeCore.WM_MOUSEMOVE: if (_childWindowType == ChildWindowType.DropDownList) From a763143f2bf3e912000c763ecc90ff58a6d1beb1 Mon Sep 17 00:00:00 2001 From: JayashreeSF3546 Date: Fri, 5 Jun 2026 16:01:48 +0530 Subject: [PATCH 2/6] added calculate height method --- .../Forms/Controls/ComboBox/ComboBox.cs | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/System.Windows.Forms/System/Windows/Forms/Controls/ComboBox/ComboBox.cs b/src/System.Windows.Forms/System/Windows/Forms/Controls/ComboBox/ComboBox.cs index 5e4422eaf9c..86e36af873c 100644 --- a/src/System.Windows.Forms/System/Windows/Forms/Controls/ComboBox/ComboBox.cs +++ b/src/System.Windows.Forms/System/Windows/Forms/Controls/ComboBox/ComboBox.cs @@ -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) { @@ -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, From 707852c4f1eee1c77229892336e735a81a820f37 Mon Sep 17 00:00:00 2001 From: JayashreeSF3546 Date: Fri, 5 Jun 2026 18:11:02 +0530 Subject: [PATCH 3/6] review changes --- .../ComboBox/ComboBox.ComboBoxChildNativeWindow.cs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/System.Windows.Forms/System/Windows/Forms/Controls/ComboBox/ComboBox.ComboBoxChildNativeWindow.cs b/src/System.Windows.Forms/System/Windows/Forms/Controls/ComboBox/ComboBox.ComboBoxChildNativeWindow.cs index 61544466151..be9d1dca835 100644 --- a/src/System.Windows.Forms/System/Windows/Forms/Controls/ComboBox/ComboBox.ComboBoxChildNativeWindow.cs +++ b/src/System.Windows.Forms/System/Windows/Forms/Controls/ComboBox/ComboBox.ComboBoxChildNativeWindow.cs @@ -33,18 +33,22 @@ protected override unsafe void WndProc(ref Message m) // 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) + WINDOWPOS* wp = (WINDOWPOS*)(nint)m.LParamInternal; + if (wp is not null && (wp->flags & SET_WINDOW_POS_FLAGS.SWP_NOSIZE) == 0) { var height = _owner.GetCalculatedDropDownHeight(); - if (pos->cy != height) + if (wp->cy != height) { - pos->cy = height; + wp->cy = height; } } } + else + { + _owner.ChildWndProc(ref m); + } - return; + break; case PInvokeCore.WM_MOUSEMOVE: if (_childWindowType == ChildWindowType.DropDownList) { From 9f33e17a43d9b03e27c69e95cb08d8c2733948d9 Mon Sep 17 00:00:00 2001 From: JayashreeSF3546 Date: Wed, 10 Jun 2026 16:14:16 +0530 Subject: [PATCH 4/6] added test cases --- .../System/Windows/Forms/ComboBoxTests.cs | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/src/test/unit/System.Windows.Forms/System/Windows/Forms/ComboBoxTests.cs b/src/test/unit/System.Windows.Forms/System/Windows/Forms/ComboBoxTests.cs index bcb46fd6318..fc4d635b33b 100644 --- a/src/test/unit/System.Windows.Forms/System/Windows/Forms/ComboBoxTests.cs +++ b/src/test/unit/System.Windows.Forms/System/Windows/Forms/ComboBoxTests.cs @@ -2742,6 +2742,60 @@ public void ComboBox_CorrectHeightAfterSetDropDownStyleSimple() handleCreatedInvoked.Should().Be(2); } + [WinFormsFact] + public void ComboBox_GetCalculatedDropDownHeight_Reflects_Items_Clear() + { + using ComboBox combo = new(); + combo.DropDownStyle = ComboBoxStyle.DropDown; + + // Add items to influence calculated height and create handle. + for (int i = 0; i < 20; i++) + { + combo.Items.Add($"item{i}"); + } + + Assert.NotEqual(IntPtr.Zero, combo.Handle); + + MethodInfo mi = typeof(ComboBox).GetMethod("GetCalculatedDropDownHeight", BindingFlags.Instance | BindingFlags.NonPublic); + Assert.NotNull(mi); + + int heightWithItems = (int)mi.Invoke(combo, null); + + combo.Items.Clear(); + + mi = typeof(ComboBox).GetMethod("GetCalculatedDropDownHeight", BindingFlags.Instance | BindingFlags.NonPublic); + Assert.NotNull(mi); + int heightAfterClear = (int)mi.Invoke(combo, null); + + // After clearing items the calculated height should change and not remain the previous items height. + Assert.NotEqual(heightWithItems, heightAfterClear); + } + + [WinFormsFact] + public void ComboBox_GetCalculatedDropDownHeight_Uses_DropDownHeight_When_NoItems() + { + using ComboBox combo = new(); + combo.DropDownStyle = ComboBoxStyle.DropDown; + + // Add items to influence calculated height and create handle. + for (int i = 0; i < 2; i++) + { + combo.Items.Add($"item{i}"); + } + + // Ensure handle exists and items are empty. + Assert.NotEqual(IntPtr.Zero, combo.Handle); + combo.Items.Clear(); + + MethodInfo mi = typeof(ComboBox).GetMethod("GetCalculatedDropDownHeight", BindingFlags.Instance | BindingFlags.NonPublic); + Assert.NotNull(mi); + + int calculated = (int)mi.Invoke(combo, null); + + // Calculated height should not exceed the explicit DropDownHeight when there are no items. + Assert.InRange(calculated, 0, combo.DropDownHeight); + } + private void InitializeItems(ComboBox comboBox, int numItems) { for (int i = 0; i < numItems; i++) From 67bec0e309a5c2a70036706dff85103bfbf46ef8 Mon Sep 17 00:00:00 2001 From: JayashreeSF3546 Date: Wed, 10 Jun 2026 16:33:34 +0530 Subject: [PATCH 5/6] review changes --- .../ComboBox.ComboBoxChildNativeWindow.cs | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/System.Windows.Forms/System/Windows/Forms/Controls/ComboBox/ComboBox.ComboBoxChildNativeWindow.cs b/src/System.Windows.Forms/System/Windows/Forms/Controls/ComboBox/ComboBox.ComboBoxChildNativeWindow.cs index be9d1dca835..6d26d4d70f5 100644 --- a/src/System.Windows.Forms/System/Windows/Forms/Controls/ComboBox/ComboBox.ComboBoxChildNativeWindow.cs +++ b/src/System.Windows.Forms/System/Windows/Forms/Controls/ComboBox/ComboBox.ComboBoxChildNativeWindow.cs @@ -33,15 +33,8 @@ protected override unsafe void WndProc(ref Message m) // 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* wp = (WINDOWPOS*)(nint)m.LParamInternal; - if (wp is not null && (wp->flags & SET_WINDOW_POS_FLAGS.SWP_NOSIZE) == 0) - { - var height = _owner.GetCalculatedDropDownHeight(); - if (wp->cy != height) - { - wp->cy = height; - } - } + WmWindowPosChanging(ref m); + DefWndProc(ref m); } else { @@ -177,5 +170,18 @@ private unsafe void WmGetObject(ref Message m) throw new InvalidOperationException(SR.RichControlLresult, e); } } + + private unsafe void WmWindowPosChanging(ref Message m) + { + 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; + } + } + } } } From cd0c96fe79335f73e43b5a91fda84371cf507115 Mon Sep 17 00:00:00 2001 From: JayashreeSF3546 Date: Wed, 10 Jun 2026 16:42:03 +0530 Subject: [PATCH 6/6] review changes --- .../ComboBox/ComboBox.ComboBoxChildNativeWindow.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/System.Windows.Forms/System/Windows/Forms/Controls/ComboBox/ComboBox.ComboBoxChildNativeWindow.cs b/src/System.Windows.Forms/System/Windows/Forms/Controls/ComboBox/ComboBox.ComboBoxChildNativeWindow.cs index 6d26d4d70f5..0ff802ec8e9 100644 --- a/src/System.Windows.Forms/System/Windows/Forms/Controls/ComboBox/ComboBox.ComboBoxChildNativeWindow.cs +++ b/src/System.Windows.Forms/System/Windows/Forms/Controls/ComboBox/ComboBox.ComboBoxChildNativeWindow.cs @@ -28,11 +28,6 @@ protected override unsafe void WndProc(ref Message m) case PInvokeCore.WM_WINDOWPOSCHANGING: if (_childWindowType == ChildWindowType.DropDownList) { - // 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. WmWindowPosChanging(ref m); DefWndProc(ref m); } @@ -173,6 +168,11 @@ private unsafe void WmGetObject(ref Message m) 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) {