WinForms 深层嵌套控件调整大小内核错误 - 拆分面板无法正确缩放控件

WinForms deep nested controls resize kernel bug - Splitter Panels not scaling controls properly

(嵌套的初步猜测被证明是不正确的。问题似乎是 SplitContainer 面板没有正确缩放它们的托管控件。)


我有一些带有选项卡控件的表单在加载时无法正确调整大小。 https://support.microsoft.com/en-us/kb/953934 在 2008 年描述了这样一个内核错误。很难相信它还没有被修复。我认为它消失了一段时间,但我又开始看到问题了。

控件嵌套得很深。 Midi 父级、子级窗体、选项卡控件、带有两个面板和控件的拆分器控件。对于自上而下的问题,第一个控件是选项卡控件。它会在加载后调整表单大小时调整大小,但锚点不正确并且部分控件被剪裁。

该问题似乎特定于 100% 桌面字体大小 - 100+ 大小的桌面工作正常。我使用 VS 2013 v5 进行了 125% 的开发——这个问题也出现在 v4 上。

有人知道知识库文章中概述的自定义控件的变通方法吗?

还有什么我错过的吗?


仔细观察,SplitContainer 是控件而不是 resizing/honoring 锚点。


我在选项卡显示后尝试了 运行 这段代码,但它不起作用 - 看起来与使用锚点大致相同。 TabControl 似乎报告了不正确的 ClientSize

    SplitContainer1.Width = TabControl1.ClientSize.Width - 10
    SplitContainer1.Height = TabControl1.ClientSize.Height - TabControl1.ItemSize.Height - 10

这是显示问题的完整表格。在 125% 的桌面上,它显示为 IDE 在 100% 的桌面上,选项卡上的控件位置不正确。

<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class frmChild
Inherits System.Windows.Forms.Form

'Form overrides dispose to clean up the component list.
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
    Try
        If disposing AndAlso components IsNot Nothing Then
            components.Dispose()
        End If
    Finally
        MyBase.Dispose(disposing)
    End Try
End Sub

'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.  
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
    Me.TabControl1 = New System.Windows.Forms.TabControl()
    Me.TabPage1 = New System.Windows.Forms.TabPage()
    Me.SplitContainer1 = New System.Windows.Forms.SplitContainer()
    Me.Button1 = New System.Windows.Forms.Button()
    Me.TabPage2 = New System.Windows.Forms.TabPage()
    Me.TextBox1 = New System.Windows.Forms.TextBox()
    Me.Button2 = New System.Windows.Forms.Button()
    Me.TabControl1.SuspendLayout()
    Me.TabPage1.SuspendLayout()
    CType(Me.SplitContainer1, System.ComponentModel.ISupportInitialize).BeginInit()
    Me.SplitContainer1.Panel1.SuspendLayout()
    Me.SplitContainer1.Panel2.SuspendLayout()
    Me.SplitContainer1.SuspendLayout()
    Me.SuspendLayout()
    '
    'TabControl1
    '
    Me.TabControl1.Anchor = CType((((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Bottom) _
        Or System.Windows.Forms.AnchorStyles.Left) _
        Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
    Me.TabControl1.Controls.Add(Me.TabPage1)
    Me.TabControl1.Controls.Add(Me.TabPage2)
    Me.TabControl1.Location = New System.Drawing.Point(82, 2)
    Me.TabControl1.Name = "TabControl1"
    Me.TabControl1.SelectedIndex = 0
    Me.TabControl1.Size = New System.Drawing.Size(466, 436)
    Me.TabControl1.TabIndex = 2
    '
    'TabPage1
    '
    Me.TabPage1.Controls.Add(Me.SplitContainer1)
    Me.TabPage1.Location = New System.Drawing.Point(4, 25)
    Me.TabPage1.Name = "TabPage1"
    Me.TabPage1.Padding = New System.Windows.Forms.Padding(3)
    Me.TabPage1.Size = New System.Drawing.Size(458, 407)
    Me.TabPage1.TabIndex = 0
    Me.TabPage1.Text = "TabPage1"
    Me.TabPage1.UseVisualStyleBackColor = True
    '
    'SplitContainer1
    '
    Me.SplitContainer1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
    Me.SplitContainer1.Dock = System.Windows.Forms.DockStyle.Fill
    Me.SplitContainer1.Location = New System.Drawing.Point(3, 3)
    Me.SplitContainer1.Name = "SplitContainer1"
    Me.SplitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal
    '
    'SplitContainer1.Panel1
    '
    Me.SplitContainer1.Panel1.Controls.Add(Me.Button2)
    Me.SplitContainer1.Panel1.Controls.Add(Me.TextBox1)
    '
    'SplitContainer1.Panel2
    '
    Me.SplitContainer1.Panel2.Controls.Add(Me.Button1)
    Me.SplitContainer1.Size = New System.Drawing.Size(452, 401)
    Me.SplitContainer1.SplitterDistance = 223
    Me.SplitContainer1.TabIndex = 0
    '
    'Button1
    '
    Me.Button1.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
    Me.Button1.Location = New System.Drawing.Point(371, 146)
    Me.Button1.Name = "Button1"
    Me.Button1.Size = New System.Drawing.Size(75, 23)
    Me.Button1.TabIndex = 0
    Me.Button1.Text = "Button1"
    Me.Button1.UseVisualStyleBackColor = True
    '
    'TabPage2
    '
    Me.TabPage2.Location = New System.Drawing.Point(4, 25)
    Me.TabPage2.Name = "TabPage2"
    Me.TabPage2.Padding = New System.Windows.Forms.Padding(3)
    Me.TabPage2.Size = New System.Drawing.Size(854, 450)
    Me.TabPage2.TabIndex = 1
    Me.TabPage2.Text = "TabPage2"
    Me.TabPage2.UseVisualStyleBackColor = True
    '
    'TextBox1
    '
    Me.TextBox1.Anchor = CType((((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Bottom) _
        Or System.Windows.Forms.AnchorStyles.Left) _
        Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
    Me.TextBox1.BackColor = System.Drawing.SystemColors.Info
    Me.TextBox1.Location = New System.Drawing.Point(17, 13)
    Me.TextBox1.Multiline = True
    Me.TextBox1.Name = "TextBox1"
    Me.TextBox1.ScrollBars = System.Windows.Forms.ScrollBars.Vertical
    Me.TextBox1.Size = New System.Drawing.Size(344, 177)
    Me.TextBox1.TabIndex = 0
    '
    'Button2
    '
    Me.Button2.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
    Me.Button2.Location = New System.Drawing.Point(371, 195)
    Me.Button2.Name = "Button2"
    Me.Button2.Size = New System.Drawing.Size(75, 23)
    Me.Button2.TabIndex = 1
    Me.Button2.Text = "Button2"
    Me.Button2.UseVisualStyleBackColor = True
    '
    'frmChild
    '
    Me.AutoScaleDimensions = New System.Drawing.SizeF(120.0!, 120.0!)
    Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi
    Me.ClientSize = New System.Drawing.Size(548, 439)
    Me.Controls.Add(Me.TabControl1)
    Me.Name = "frmChild"
    Me.Text = "frmChild"
    Me.TabControl1.ResumeLayout(False)
    Me.TabPage1.ResumeLayout(False)
    Me.SplitContainer1.Panel1.ResumeLayout(False)
    Me.SplitContainer1.Panel1.PerformLayout()
    Me.SplitContainer1.Panel2.ResumeLayout(False)
    CType(Me.SplitContainer1, System.ComponentModel.ISupportInitialize).EndInit()
    Me.SplitContainer1.ResumeLayout(False)
    Me.ResumeLayout(False)

End Sub
Friend WithEvents TabControl1 As System.Windows.Forms.TabControl
Friend WithEvents TabPage1 As System.Windows.Forms.TabPage
Friend WithEvents SplitContainer1 As System.Windows.Forms.SplitContainer
Friend WithEvents Button1 As System.Windows.Forms.Button
Friend WithEvents TabPage2 As System.Windows.Forms.TabPage
Friend WithEvents Button2 As System.Windows.Forms.Button
Friend WithEvents TextBox1 As System.Windows.Forms.TextBox
End Class

如果 SplitPanel 没有正确锚定其内容,您可以尝试将内容放入另一个错误较少的容器中。

试着把 TableLayoutPanel 放在 SplitPanel 里面。将 TableLayoutPanel.Dock 属性 设置为 Fill,然后 .Anchor 您在其中的控件。 (不要在 TableLayoutPanel 中使用 .Dock,它有点不稳定)。

TableLayoutPanel 中的控件将具有名为 .RowSpan.ColumnSpan 的新属性,它们允许控件跨越多个单元格。

TableLayoutPanel 右上角有一个小箭头,可让您编辑行和列。我发现最好的办法是尽可能多地固定 width/height,然后使用百分比来处理其余部分。我不使用 Autosize,但你可以试试。