diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Control.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Control.cs index 64e8562c4fd..74768e63256 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/Control.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/Control.cs @@ -9629,6 +9629,9 @@ internal virtual void RecreateHandleCore() // the call shouldn't fail. // However, it could fail if this.CreateParams.Parent is changed outside our control. CreateHandle(); + + // DestroyHandle resets the state, but CreateHandle doesn't set the state back. + SetState(States.Created, true); } catch (Exception) { diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ControlTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ControlTests.cs index 2c5b6d5a4a9..9f0f78df088 100644 --- a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ControlTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ControlTests.cs @@ -722,6 +722,62 @@ public void Control_CreateParams_GetVisible_ReturnsExpected(bool visible, int ex Assert.False(control.IsHandleCreated); } + [WinFormsFact] + public void Control_RecreateHandleCore_invokes_OnParentHandleRecreated_for_children() + { + using Form form = new(); + SubCheckedListBox checkedListBox1 = new(); + SubButton button1 = new(); + SubListBox listBox1 = new(); + SubListView listView1 = new(); + + checkedListBox1.Items.AddRange(new object[] { "Foo", "Foo", "Foo" }); + checkedListBox1.Location = new Point(10, 10); + checkedListBox1.Size = new Size(103, 64); + + button1.Location = new Point(12, 166); + button1.Size = new Size(213, 20); + + listBox1.Items.AddRange(new object[] { "Foo", "Foo", "Foo" }); + listBox1.Location = new Point(12, 80); + listBox1.Size = new Size(101, 69); + + listView1.Items.AddRange(new ListViewItem[] { new("Foo"), new("Foo"), new("Foo") }); + listView1.Location = new Point(130, 10); + listView1.Size = new Size(121, 64); + listView1.View = View.List; + + form.Controls.Add(checkedListBox1); + form.Controls.Add(button1); + form.Controls.Add(listBox1); + form.Controls.Add(listView1); + + form.Show(); + + // This will recreate the handle. + form.ShowInTaskbar = false; + + try + { + AssertHandler(button1); + AssertHandler(listView1); + AssertHandler(checkedListBox1); + AssertHandler(listBox1); + } + finally + { + form.Close(); + } + + return; + + static void AssertHandler(IParentHandleRecreationHandler handler) + { + Assert.Equal(1, handler.OnParentHandleRecreatedCalled); + Assert.Equal(1, handler.OnParentHandleRecreatingCalled); + } + } + private class SubControl : Control { public SubControl() : base() @@ -1046,5 +1102,83 @@ public SubControl(Control parent, string text, int left, int top, int width, int public new void WndProc(ref Message m) => base.WndProc(ref m); } + + private class SubCheckedListBox : CheckedListBox, IParentHandleRecreationHandler + { + public int OnParentHandleRecreatedCalled { get; private set; } + public int OnParentHandleRecreatingCalled { get; private set; } + + internal override void OnParentHandleRecreated() + { + OnParentHandleRecreatedCalled++; + base.OnParentHandleRecreated(); + } + + internal override void OnParentHandleRecreating() + { + OnParentHandleRecreatingCalled++; + base.OnParentHandleRecreating(); + } + } + + private class SubListBox : ListBox, IParentHandleRecreationHandler + { + public int OnParentHandleRecreatedCalled { get; private set; } + public int OnParentHandleRecreatingCalled { get; private set; } + + internal override void OnParentHandleRecreated() + { + OnParentHandleRecreatedCalled++; + base.OnParentHandleRecreated(); + } + + internal override void OnParentHandleRecreating() + { + OnParentHandleRecreatingCalled++; + base.OnParentHandleRecreating(); + } + } + + private class SubButton : Button, IParentHandleRecreationHandler + { + public int OnParentHandleRecreatedCalled { get; private set; } + public int OnParentHandleRecreatingCalled { get; private set; } + + internal override void OnParentHandleRecreated() + { + OnParentHandleRecreatedCalled++; + base.OnParentHandleRecreated(); + } + + internal override void OnParentHandleRecreating() + { + OnParentHandleRecreatingCalled++; + base.OnParentHandleRecreating(); + } + } + + private class SubListView : ListView, IParentHandleRecreationHandler + { + public int OnParentHandleRecreatedCalled { get; private set; } + public int OnParentHandleRecreatingCalled { get; private set; } + + internal override void OnParentHandleRecreated() + { + OnParentHandleRecreatedCalled++; + base.OnParentHandleRecreated(); + } + + internal override void OnParentHandleRecreating() + { + OnParentHandleRecreatingCalled++; + base.OnParentHandleRecreating(); + } + } + + private interface IParentHandleRecreationHandler + { + int OnParentHandleRecreatedCalled { get; } + int OnParentHandleRecreatingCalled { get; } + } } }