经过更多调试后,我发现重新排序与创建句柄有关。
首次打开表单时,所有面板都是可见的(因为我在设计时没有更改它)并且所有句柄都会立即创建,然后一些句柄会被Form.Shown
事件处理程序隐藏。当窗体关闭时,句柄将丢失。但是,如果 Form 第二次显示,则只有在 Form 关闭时可见的 Panel 的句柄会立即重新创建。一旦控件变得可见(正如 MSDN 指出的那样),就会创建每个句柄,但显然现在显示控件的顺序很重要,因为控件可以在创建句柄时在父控件的 ControlCollection 中移动。
事实证明,当第二次显示表单时,在显示某个面板(此处为 PanelToBecomeVisible)之前,控制顺序为:
0 Panel1
1 h InitiallyVisibleButLaterHiddenPanel
2 Panel2
3 PanelToBecomeVisible
4 vh AlwaysVisibleTopMostPanel
其中 v 表示可见,h 表示 IsHandleCreated 为真。之后
PanelToBecomeVisible.Visible = True
ControlCollection 看起来像这样:
0 Panel1
1 h InitiallyVisibleButLaterHiddenPanel
2 vh PanelToBecomeVisible
3 Panel2
4 vh AlwaysVisibleTopMostPanel
如果 Panel2 稍后变得可见,它将随后与 PanelToBecomeVisible 交换位置。
因此,一种解决方案是确保尽早创建所有句柄,即使面板尚不可见。这可以通过Handle
像这样访问每个有问题的控件的属性来实现,例如:
Private Sub Form_Shown(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Shown
Dim h As IntPtr
For Each ctrl As Control In ParentControl.Controls
h = ctrl.Handle
Next
End Sub