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

时间:2015-07-28 16:47:51

标签: vb.net winforms windows-kernel

(initial guess at nested proved to be incorrect. Problem seems to be that SplitContainer panels do not scale their hosted controls properly.)


I have some forms that have tab controls that fail to resize properly at load time. https://support.microsoft.com/en-us/kb/953934 describes such a kernel bug in 2008. Hard to believe it hasn't been fixed. I think it went away for a while but I'm beginning to see problems again.

The controls are nested pretty deep. Midi Parent, child form, tab control, splitter control with two panels and controls. For the top down the first control with the problem is the tab control. It resizes when the form is resized after loading but the anchors are incorrect and part of the control is clipped.

The problem seems to be specific to 100% desktop font size - desktops with 100+ size work OK. I develop at 125% using VS 2013 v5 - the issue was present on v4 as well.

Anyone know of a work around short of the custom control as outlined in the KB article?

Something else going on I've missed?


Looking at it more closely the SplitContainer is the control not resizing/honoring the anchors.


I tried running this code after the tab was shown and it didn't work - looks about the same as using anchors. It seems that the TabControl is reporting an incorrect ClientSize

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

Here is a complete form that shows the problem. On a 125% desktop it shows as in the IDE on a 100% desktop the controls on the tab are not positioned properly.

<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

1 个答案:

答案 0 :(得分:1)

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

尝试在TableLayoutPanel内加SplitPanel。将TableLayoutPanel.Dock属性设置为Fill,然后将.Anchor内部的控件设置为.Dock。 (不要在TableLayoutPanel内使用TableLayoutPanel,它有点不稳定。

.RowSpan内的控件将包含名为.ColumnSpanTableLayoutPanel的新属性,这些属性允许控件跨越多个单元格。

Autosize右上角有一个小箭头,可以编辑行和列。我发现最好的是尽可能多地固定宽度/高度,然后使用百分比。我不使用private static void SetupServer() { Console.WriteLine("Setting up server..."); serverSocket.Bind(new IPEndPoint(IPAddress.Any, 100)); serverSocket.Listen(1); serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null); } 但您可以试试。