3

我有一个表格,上面有一些控件(面板、组框等),它们都已control.Dock = DockStyle.Top设置。根据表单上组合框的选定值,只有其中一些面板应该同时可见(因为隐藏的面板不适用于选定的选项)。对接是为了让 UI 显得更加紧凑。

每当 ComboBox 选择发生变化时以及在 Form 的 Shown 事件上发生变化时,这些 Panel 的 Visible 属性都会发生变化(因为当 Form 第一次显示并且 ComboBox 选择尚未更改时,并非所有 Panel 都应该可见)。

现在,问题是,当我关闭表单时(因为它是一个模式对话框,它没有被破坏),稍后重新打开它并更改组合框选择,表单顶部的面板的显示顺序已经改变。直到表格被关闭一次才会发生。我知道停靠控件的显示顺序与父控件的 ControlCollection 中这些控件的顺序相关联。这也决定了控件的 z 顺序,因此也决定了问题的标题。

是什么导致控制顺序发生变化以及如何避免它?

4

1 回答 1

5

经过更多调试后,我发现重新排序与创建句柄有关。

首次打开表单时,所有面板都是可见的(因为我在设计时没有更改它)并且所有句柄都会立即创建,然后一些句柄会被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 = TrueControlCollection 看起来像这样:

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
于 2011-04-25T09:40:57.293 回答