From fe22312974ed2f46a41adaf10f1994adfc83fbeb Mon Sep 17 00:00:00 2001 From: "Leaf Shi (BEYONDSOFT CONSULTING INC)" Date: Fri, 6 Dec 2024 16:00:22 +0800 Subject: [PATCH 1/4] Set MouseIsOver = false in OnLostFocus method --- .../src/System/Windows/Forms/Controls/ComboBox/ComboBox.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Controls/ComboBox/ComboBox.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Controls/ComboBox/ComboBox.cs index 2ba076ddf47..45f1b864695 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Controls/ComboBox/ComboBox.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Controls/ComboBox/ComboBox.cs @@ -2747,6 +2747,12 @@ protected override void OnLostFocus(EventArgs e) base.OnLostFocus(e); _canFireLostFocus = false; + + // If the dropdown is not active, that means the mouse is no longer over the control. + if (!DroppedDown) + { + MouseIsOver = false; + } } } @@ -3826,7 +3832,6 @@ protected override unsafe void WndProc(ref Message m) base.WndProc(ref m); ReleaseChildWindow(); break; - default: if (m.MsgInternal == RegisteredMessage.WM_MOUSEENTER) { From fb992f4c2a001d8985895fbd4a755b1b95782da6 Mon Sep 17 00:00:00 2001 From: "Leaf Shi (BEYONDSOFT CONSULTING INC)" Date: Fri, 6 Dec 2024 16:20:03 +0800 Subject: [PATCH 2/4] Remove extra blank line --- .../src/System/Windows/Forms/Controls/ComboBox/ComboBox.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Controls/ComboBox/ComboBox.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Controls/ComboBox/ComboBox.cs index 45f1b864695..2da20e8a72f 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Controls/ComboBox/ComboBox.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Controls/ComboBox/ComboBox.cs @@ -3832,6 +3832,7 @@ protected override unsafe void WndProc(ref Message m) base.WndProc(ref m); ReleaseChildWindow(); break; + default: if (m.MsgInternal == RegisteredMessage.WM_MOUSEENTER) { From 44bafafcc51c95f76d179b8683ffae6b2601a869 Mon Sep 17 00:00:00 2001 From: "Leaf Shi (BEYONDSOFT CONSULTING INC)" Date: Mon, 9 Dec 2024 16:38:00 +0800 Subject: [PATCH 3/4] Add unit test --- .../Forms/Controls/ComboBox/ComboBox.cs | 4 +-- .../System/Windows/Forms/ComboBoxTests.cs | 32 +++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Controls/ComboBox/ComboBox.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Controls/ComboBox/ComboBox.cs index 2da20e8a72f..bde81573233 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Controls/ComboBox/ComboBox.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Controls/ComboBox/ComboBox.cs @@ -2748,8 +2748,8 @@ protected override void OnLostFocus(EventArgs e) base.OnLostFocus(e); _canFireLostFocus = false; - // If the dropdown is not active, that means the mouse is no longer over the control. - if (!DroppedDown) + // When the control loses focus, reset the MouseIsOver to False. + if (DropDownStyle == ComboBoxStyle.Simple || !DroppedDown) { MouseIsOver = false; } diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ComboBoxTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ComboBoxTests.cs index fbf943b8265..beea80647f1 100644 --- a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ComboBoxTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ComboBoxTests.cs @@ -2750,6 +2750,38 @@ private void InitializeItems(ComboBox comboBox, int numItems) Assert.Equal(numItems, comboBox.Items.Count); } + [WinFormsFact] + public void ComboBox_OnLostFocus_AutoCompleteModeNone_DoesNotClearMatchingText() + { + using ComboBox comboBox = new(); + comboBox.TestAccessor().Dynamic._canFireLostFocus= true; + comboBox.AutoCompleteMode = AutoCompleteMode.None; + comboBox.AutoCompleteSource = AutoCompleteSource.ListItems; + comboBox.TestAccessor().Dynamic.MatchingText = "Test"; + comboBox.DropDownStyle = ComboBoxStyle.Simple; + comboBox.TestAccessor().Dynamic.OnLostFocus(EventArgs.Empty); + + string matchingText = comboBox.TestAccessor().Dynamic.MatchingText; + matchingText.Should().Be("Test"); + comboBox.MouseIsOver.Should().BeFalse(); + } + + [WinFormsFact] + public void ComboBox_OnLostFocus_AutoCompleteModeNotNone_ClearsMatchingText() + { + using ComboBox comboBox = new(); + comboBox.TestAccessor().Dynamic._canFireLostFocus = true; + comboBox.AutoCompleteMode = AutoCompleteMode.Suggest; + comboBox.AutoCompleteSource = AutoCompleteSource.ListItems; + comboBox.DropDownStyle = ComboBoxStyle.DropDownList; + comboBox.TestAccessor().Dynamic.MatchingText = "Test"; + comboBox.TestAccessor().Dynamic.OnLostFocus(EventArgs.Empty); + + string matchingText = comboBox.TestAccessor().Dynamic.MatchingText; + matchingText.Should().BeEmpty(); + comboBox.MouseIsOver.Should().BeFalse(); + } + private class OwnerDrawComboBox : ComboBox { public OwnerDrawComboBox() From 9aa73b01e3b02cf6648a92c76b8f0a0a9e9f115b Mon Sep 17 00:00:00 2001 From: "Leaf Shi (BEYONDSOFT CONSULTING INC)" Date: Thu, 12 Dec 2024 15:31:34 +0800 Subject: [PATCH 4/4] Update test cases and the logic of the DrawPopUpCombo --- .../Forms/Controls/ComboBox/ComboBox.cs | 5 +++- .../System/Windows/Forms/ComboBoxTests.cs | 24 ++++++++++++------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Controls/ComboBox/ComboBox.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Controls/ComboBox/ComboBox.cs index bde81573233..634c2b60f54 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Controls/ComboBox/ComboBox.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Controls/ComboBox/ComboBox.cs @@ -3770,7 +3770,10 @@ protected override unsafe void WndProc(ref Message m) } using Graphics g = Graphics.FromHdcInternal((IntPtr)dc); - if ((!Enabled || FlatStyle == FlatStyle.Popup) && MouseIsOver) + + // The pop up border needs to be drawn only when the control gets the focus or the mouse hovers over it. + bool isPopupAndActive = FlatStyle == FlatStyle.Popup && (Focused || MouseIsOver); + if (!Enabled || isPopupAndActive) { FlatComboBoxAdapter.DrawPopUpCombo(this, g); } diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ComboBoxTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ComboBoxTests.cs index beea80647f1..7aa5269adf2 100644 --- a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ComboBoxTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ComboBoxTests.cs @@ -2754,15 +2754,19 @@ private void InitializeItems(ComboBox comboBox, int numItems) public void ComboBox_OnLostFocus_AutoCompleteModeNone_DoesNotClearMatchingText() { using ComboBox comboBox = new(); - comboBox.TestAccessor().Dynamic._canFireLostFocus= true; + var comboBoxAccessor = comboBox.TestAccessor().Dynamic; + comboBoxAccessor._canFireLostFocus= true; comboBox.AutoCompleteMode = AutoCompleteMode.None; comboBox.AutoCompleteSource = AutoCompleteSource.ListItems; - comboBox.TestAccessor().Dynamic.MatchingText = "Test"; + comboBoxAccessor.MatchingText = "Test"; comboBox.DropDownStyle = ComboBoxStyle.Simple; - comboBox.TestAccessor().Dynamic.OnLostFocus(EventArgs.Empty); + comboBoxAccessor.OnLostFocus(EventArgs.Empty); - string matchingText = comboBox.TestAccessor().Dynamic.MatchingText; + string matchingText = comboBoxAccessor.MatchingText; matchingText.Should().Be("Test"); + + // Verifies the fix for issue "https://github.com/dotnet/winforms/issues/12590" + // related to ComboBox dropdown button disappear when switching RightToLeft property. comboBox.MouseIsOver.Should().BeFalse(); } @@ -2770,15 +2774,19 @@ public void ComboBox_OnLostFocus_AutoCompleteModeNone_DoesNotClearMatchingText() public void ComboBox_OnLostFocus_AutoCompleteModeNotNone_ClearsMatchingText() { using ComboBox comboBox = new(); - comboBox.TestAccessor().Dynamic._canFireLostFocus = true; + var comboBoxAccessor = comboBox.TestAccessor().Dynamic; + comboBoxAccessor._canFireLostFocus = true; comboBox.AutoCompleteMode = AutoCompleteMode.Suggest; comboBox.AutoCompleteSource = AutoCompleteSource.ListItems; comboBox.DropDownStyle = ComboBoxStyle.DropDownList; - comboBox.TestAccessor().Dynamic.MatchingText = "Test"; - comboBox.TestAccessor().Dynamic.OnLostFocus(EventArgs.Empty); + comboBoxAccessor.MatchingText = "Test"; + comboBoxAccessor.OnLostFocus(EventArgs.Empty); - string matchingText = comboBox.TestAccessor().Dynamic.MatchingText; + string matchingText = comboBoxAccessor.MatchingText; matchingText.Should().BeEmpty(); + + // Verifies the fix for issue "https://github.com/dotnet/winforms/issues/12590" + // related to ComboBox dropdown button disappear when switching RightToLeft property. comboBox.MouseIsOver.Should().BeFalse(); }