由于 Winforms 中的 AutoSize 不起作用,如何创建动态布局?

how to create dynamic layout since AutoSize in winforms doesn't work?

尝试在 PowerShell 中创建简单的 win 窗体。会有一些自动计算的复选框,我正在为大小而苦苦挣扎 - 似乎 'AutoSize' 是胡说八道,返回的值不知从何而来。任何人都可以帮助并建议您如何创建动态定位吗?基于哪些值?

Add-Type -AssemblyName System.Drawing
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Application]::EnableVisualStyles()

$nrOfNIC = 2
$nrOfDisks = 3
$nrOfPIP = 1

$vShift = 20
$allChkb = 1


$chkForm = New-Object system.Windows.Forms.Form
$chkForm.text = "Remove Resources"
$chkForm.Font = New-Object System.Drawing.Font('Microsoft Sans Serif', 10)
$chkForm.AutoSize = $true
$chkForm.StartPosition = 'CenterScreen'
$chkForm.FormBorderStyle = 'Fixed3D'
$chkForm.Icon = [System.Drawing.SystemIcons]::Question
$chkForm.Topmost = $true
$chkForm.MaximizeBox = $false

$chkVMBox = new-object System.Windows.Forms.GroupBox
#$chkVMBox.MinimumSize = New-Object System.Drawing.Size(180,100) 
$chkVMBox.AutoSize = $true
$chkVMBox.Location = New-Object System.Drawing.Point(10,10)
$chkVMBox.Text = 'VM resources'
#$chkVMBox.Anchor = 'left,top'
#$lastControl = $chkVMBox

if($nrOfDisks -gt 0) {

    $chkVMDisks = new-object System.Windows.Forms.GroupBox
    #$chkVMDisks.MinimumSize = New-Object System.Drawing.Size(180,20) 
    $chkVMDisks.Location = New-Object System.Drawing.Point(10,20)
    $chkVMDisks.Text = 'DISKs'
    #$chkVMDisks.Anchor = 'left,top'

    for($disk=0;$disk -lt $nrOfDisks;$disk++) {

        $chkbDisk = New-Object System.Windows.Forms.Checkbox 
        $chkbDisk.Location = New-Object System.Drawing.Point(10, ($vShift+($disk*$vShift)) ) 
        #$chkbDisk.Anchor = 'left,top'
        $chkbDisk.AutoSize = $true
        $chkbDisk.Text = "disk $disk"
        $chkbDisk.TabIndex = $allChkb++
        $chkVMDisks.Controls.Add($chkbDisk)
        #$allChkb++
    }
    $chkVMBox.Controls.Add($chkVMDisks)
    #$lastControl=$chkVMDisks
}

if($nrOfNIC -gt 0) {
    #$vLocation = $lastControl.Bottom+$shift
    $vLocation = $chkVMDisks.Bottom+$shift

    $chkVMNICs = new-object System.Windows.Forms.GroupBox
    #$chkVMNICs.MinimumSize = New-Object System.Drawing.Size(180,20) 
    $chkVMNICs.AutoSize = $true
    $chkVMNICs.Location = New-Object System.Drawing.Point(10,$vLocation)
    $chkVMNICs.Text = 'NICs'
    #$chkVMNICs.Anchor = 'left,top'

    for($nic = 0;$nic -lt $nrOfNIC; $nic++) {
        $chkbNIC = New-Object System.Windows.Forms.Checkbox 
        $chkbNIC.Location = New-Object System.Drawing.Point(10, ($vShift+($nic*$vShift)) ) 
        #$chkbNIC.Anchor = 'left,top'
        $chkbNIC.AutoSize = $true
        $chkbNIC.Text = "nic $nic"
        $chkbNIC.TabIndex = $allChkb++
        $chkVMNICs.Controls.Add($chkbNIC)
        #$allChkb++
    }
    $chkVMBox.Controls.Add($chkVMNICs)
    #$lastControl = $chkVMNICs
}

    #$vLocation = $lastControl.Bottom+$shift
    $vLocation = $chkVMNICs.Bottom+$shift
    $chkbVMdiag = New-Object System.Windows.Forms.Checkbox 
    $chkbVMdiag.Location = New-Object System.Drawing.Point(10,$vLocation) 
    #$chkbVMdiag.Anchor = 'left,top'
    $chkbVMdiag.AutoSize = $true
    $chkbVMdiag.Text = "Boot Diagnostics"
    $chkbVMdiag.TabIndex = $allChkb++
    $chkVMBox.Controls.Add($chkbVMdiag)
    
    
    $vLocation = $chkVMBox.bottom + 40
    $btOK = New-Object System.Windows.Forms.Button
    $btOK.Location = New-Object System.Drawing.Size(15,$vLocation)
    $btOK.Size = New-Object System.Drawing.Size(70,20)
    $btOK.Text = "OK"
    $btOK.DialogResult = [System.Windows.Forms.DialogResult]::OK
    #$btOK.Anchor = 'left,bottom'

    $btCancel = New-Object System.Windows.Forms.Button
    $btCancel.Location = New-Object System.Drawing.Size(95,$vLocation)
    $btCancel.Size = New-Object System.Drawing.Size(70,20)
    $btCancel.Text = "Cancel"
    $btCancel.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
    #$btCancel.Anchor = 'right,bottom'     

$chkForm.AcceptButton = $btOK
$chkForm.CancelButton = $btCancel
$chkForm.Controls.AddRange(@($chkVMBox, $btOK, $btCancel))

[void]$chkForm.ShowDialog()

效果: effect of code

似乎 ALL VALUES 返回 'autosize' 是胡说八道。那么如何在不知道 sizes/number 预先元素的情况下创建动态布局?

  • 主窗体右边有一些大填充
  • 在复选框列表中 - 第一个有额外的 space,第二个控件 space 加倍
  • 最后一个复选框下面有一些填充

设置 .AutoSizeMode = 'GrowAndShrink' as well as .MinimumSize 属性以及 .AutoSize

  • 按钮……其实在其他控件下不可见

按钮位置源自$chkVMBox.bottom;使用 $chkForm.Controls.Add($chkVMBox) before 计算按钮的垂直位置并从 $chkForm.Controls.AddRange(…)

中删除 $chkVMBox
  • 创建动态布局,预先不知道 sizes/number 元素:

我会尝试计算控件相对于不变量的水平和垂直位置以及(最小)大小;例如,这些是根据以下代码中的 $chkForm.Font 计算得出的(愿望显然 不一致 :),请参阅 $hShift$vShift 变量,它们的值和用法。

Add-Type -AssemblyName System.Drawing
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Application]::EnableVisualStyles()
Remove-Variable chk* -ErrorAction SilentlyContinue
$nrOfNIC = 2
$nrOfDisks = 3
$nrOfPIP = 1
$allChkb = 1

$chkForm = New-Object System.Windows.Forms.Form
$chkForm.text = "Remove Resources"
$chkForm.Font = New-Object System.Drawing.Font('Microsoft Sans Serif', 10)
$hShift  = $chkForm.Font.SizeInPoints
$vShift  = $chkForm.Font.Height * 1.5  ### arbitrary ad hoc coefficient

$chkForm.StartPosition = 'CenterScreen'
$chkForm.FormBorderStyle = 'Fixed3D'
$chkForm.Icon = [System.Drawing.SystemIcons]::Question
$chkForm.Topmost = $true
$chkForm.AutoSize = $true
$chkForm.AutoSizeMode = 'GrowAndShrink'
$chkForm.MinimumSize = [System.Drawing.Size]::new(100,100)
# $chkForm.AutoScaleMode = 'Font'
$chkForm.MaximizeBox = $false
$chkForm.MinimizeBox = $false

$chkVMBox = new-object System.Windows.Forms.GroupBox
$chkVMBox.AutoSizeMode = 'GrowAndShrink'
$chkVMBox.AutoSize = $true
$chkVMBox.Location = New-Object System.Drawing.Point(10,10)
$chkVMBox.Text = 'VM resources'

if($nrOfDisks -gt 0) {

    $chkVMDisks = new-object System.Windows.Forms.GroupBox
    $chkVMDisks.Location = New-Object System.Drawing.Point($hShift,( $vShift+10))
    $chkVMDisks.Text = 'DISKs'
    $chkVMDisks.AutoSize = $true
    $chkVMDisks.MinimumSize = [System.Drawing.Size]::new(($chkVMBox.Size.Width - $hShift),$vShift)
    $chkVMDisks.AutoSizeMode = 'GrowAndShrink'

    for($disk=0;$disk -lt $nrOfDisks;$disk++) {

        $chkbDisk = New-Object System.Windows.Forms.Checkbox 
        $chkbDisk.Location = New-Object System.Drawing.Point($hShift, ($vShift*($disk+1)))
        $chkbDisk.AutoSize = $true
        $chkbDisk.Text = "disk $disk"
        $chkbDisk.TabIndex = $allChkb++
        $chkVMDisks.Controls.Add($chkbDisk)
        #$allChkb++
    }
    $chkVMBox.Controls.Add($chkVMDisks)
    #$lastControl=$chkVMDisks
}

if($nrOfNIC -gt 0) {
    #$vLocation = $lastControl.Bottom+$hShift
    $vLocation = $chkVMDisks.Bottom + $vShift

    $chkVMNICs = new-object System.Windows.Forms.GroupBox
    $chkVMNICs.AutoSize = $true
    $chkVMNICs.MinimumSize = [System.Drawing.Size]::new(($chkVMBox.Size.Width - $hShift),$vShift)
    $chkVMNICs.AutoSizeMode = 'GrowAndShrink'
    $chkVMNICs.Location = New-Object System.Drawing.Point($hShift,$vLocation)
    $chkVMNICs.Text = 'NICs'

    for($nic = 0;$nic -lt $nrOfNIC; $nic++) {
        $chkbNIC = New-Object System.Windows.Forms.Checkbox 
        $chkbNIC.Location = New-Object System.Drawing.Point($hShift, ($vShift*($nic+1)) ) 
        # $chkbNIC.Anchor = 'left,top'
        $chkbNIC.AutoSize = $true
        $chkbNIC.Text = "nic $nic"
        $chkbNIC.TabIndex = $allChkb++
        $chkVMNICs.Controls.Add($chkbNIC)
        #$allChkb++
    }
    $chkVMBox.Controls.Add($chkVMNICs)
    #$lastControl = $chkVMNICs
}

    #$vLocation = $lastControl.Bottom+$hShift
    $vLocation = $chkVMNICs.Bottom + $vShift
    $chkbVMdiag = New-Object System.Windows.Forms.Checkbox 
    $chkbVMdiag.Location = New-Object System.Drawing.Point($hShift,$vLocation) 
    $chkbVMdiag.AutoSize = $true
    $chkbVMdiag.Text = "Boot Diagnostics"
    $chkbVMdiag.TabIndex = $allChkb++
    $chkVMBox.Controls.Add($chkbVMdiag)
    
$chkForm.Controls.Add($chkVMBox)
    
    $vLocation = $chkVMBox.bottom + 20
    $btOK = New-Object System.Windows.Forms.Button
    $btOK.Location = New-Object System.Drawing.Point(15,$vLocation)
    # $btOK.Size = New-Object System.Drawing.Size(70,20)
    $btOK.AutoSize = $true
    $btOK.Text = "OK"
    $btOK.DialogResult = [System.Windows.Forms.DialogResult]::OK

    $btCancel = New-Object System.Windows.Forms.Button
    $btCancel.Location = New-Object System.Drawing.Point(95,$vLocation)
    # $btCancel.Size = New-Object System.Drawing.Size(70,20)
    $btCancel.AutoSize = $true
    $btCancel.Text = "Cancel"
    $btCancel.DialogResult = [System.Windows.Forms.DialogResult]::Cancel

$chkForm.AcceptButton = $btOK
$chkForm.CancelButton = $btCancel
$chkForm.Controls.AddRange(@($btOK, $btCancel))

[void]$chkForm.ShowDialog()
$chkForm.Dispose()