PowerShell Windows窗体包装器PowerShell表单控件包装器

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PowerShell Windows窗体包装器PowerShell表单控件包装器相关的知识,希望对你有一定的参考价值。

在PowerShell中,使用Windows Forms为小型cmdlet构建用户界面是很平常的,但是这需要的语法通常是部分冗余和安静的冗长。这导致了一个问题:是否有一种方法可以最小化所需的代码,或者是否存在PowerShell的Windows窗体包装器以减少冗长和冗余的语法? 我不是在寻找ShowUI,因为这个解决方案太重了,因为它基于Windows Presentation Foundation(另请参阅: WPF vs WinForms)以及它涉及PowerShell模块的事实,这使得部署它比包装函数更难。

答案

在很多情况下,包装器不需要使您的代码更简洁,例如冗长的WinForms PowerShell脚本here。像这样的代码片段:

$System_Windows_Forms_Padding = New-Object System.Windows.Forms.Padding
$System_Windows_Forms_Padding.All = 3
$System_Windows_Forms_Padding.Bottom = 3
$System_Windows_Forms_Padding.Left = 3
$System_Windows_Forms_Padding.Right = 3
$System_Windows_Forms_Padding.Top = 3
$Tab1.Padding = $System_Windows_Forms_Padding

可以很容易地将WinForms简化为单行:

$Tab1.Padding = 3

如果每边的填充不同,PowerShell将自动转换:

$Tab1.Padding = "4, 6, 4, 6"

注意:PowerShell不会转换$Tab1.Padding = "3"$Tab1.Padding = "4, 6"

然而,创建窗体控件的本地方式远非DRY (don't repeat yourself) programming。虽然可以在创建时添加(多个)属性(使用:New-Object System.Windows.Forms.Button -Property @{Location = "75, 120"; Size = "75, 23"}),但是在以后的状态下不能立即设置多个属性。除此之外,在创建窗体控件时,在中间添加events1,子控件和容器属性(例如RowSpan)或任何组合并不快捷。最重要的是,您必须一遍又一遍地引用窗体控件以设置其属性等(例如$OKButton.<property> = ...中的example):

$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Point(75,120)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = "OK"

这就是为什么我创建了一个可重用的PowerShell Form Control包装器,让你最小化Windows Forms(WinForms)代码。

1)除非你使用On<event>方法,另见:addEventListener vs onclick

PowerShell Form-Control Wrapper

Function Form-Control {
    [CmdletBinding(DefaultParametersetName='Self')]param(
        [Parameter(Position = 0)]$Control = "Form",
        [Parameter(Position = 1)][HashTable]$Member = @{},
        [Parameter(ParameterSetName = 'AttachChild',  Mandatory = $false)][Windows.Forms.Control[]]$Add = @(),
        [Parameter(ParameterSetName = 'AttachParent', Mandatory = $false)][HashTable]$Set = @{},
        [Parameter(ParameterSetName = 'AttachParent', Mandatory = $false)][Alias("Parent")][Switch]$GetParent,
        [Parameter(ParameterSetName = 'AttachParent', Mandatory = $true, ValueFromPipeline = $true)][Windows.Forms.Control]$Container
    )
    If ($Control -isnot [Windows.Forms.Control]) {Try {$Control = New-Object Windows.Forms.$Control} Catch {$PSCmdlet.WriteError($_)}}
    $Styles = @{RowStyles = "RowStyle"; ColumnStyles = "ColumnStyle"}
    ForEach ($Key in $Member.Keys) {
        If ($Style = $Styles.$Key) {[Void]$Control.$Key.Clear()
            For ($i = 0; $i -lt $Member.$Key.Length; $i++) {[Void]$Control.$Key.Add((New-Object Windows.Forms.$Style($Member.$Key[$i])))}
        } Else {
            Switch (($Control | Get-Member $Key).MemberType) {
                "Property"  {$Control.$Key = $Member.$Key}
                "Method"    {Invoke-Expression "[Void](`$Control.$Key($($Member.$Key)))"}
                "Event"     {Invoke-Expression "`$Control.Add_$Key(`$Member.`$Key)"}
                Default     {Write-Error("The $($Control.GetType().Name) control doesn't have a '$Key' member.")}
            }
        }
    }
    $Add | ForEach {$Control.Controls.Add($_)}
    If ($Container) {$Container.Controls.Add($Control)}
    If ($Set) {$Set.Keys | ForEach {Invoke-Expression "`$Container.Set$_(`$Control, `$Set.`$_)"}}
    If ($GetParent) {$Container} Else {$Control}
}; Set-Alias Form Form-Control

句法

创建一个控件 <System.Windows.Forms.Control> = Form-Control [-Control <String>] [-Member <HashTable>]

修改控件 <Void> = Form-Control [-Control <System.Windows.Forms.Control>] [-Member <HashTable>]

将(新)控件添加到容器中 <System.Windows.Forms.Control> = Form-Control [-Control <String>|<System.Windows.Forms.Control>] [-Member <HashTable>] [-Add <System.Windows.Forms.Control[]>]

将容器管道连接到(新)控件 <System.Windows.Forms.Control> = <System.Windows.Forms.Control> | Form-Control [-Control <String>|<System.Windows.Forms.Control>] [-Member <HashTable>] [-Set <HashTable>] [-PassParent]

参数

-Control <String>|<System.Windows.Forms.Control>(位置0,默认:Form-Control参数接受Windows窗体控件类型名称([String])或现有窗体控件([System.Windows.Forms.Control])。 Windows窗体控件类型名称类似于Form, Label, TextBox, Button, Panel, ...等。如果提供了Windows窗体控件类型名称([String]),则包装器将创建并返回一个新的Windows窗体控件,其中包含由其余参数定义的属性和设置。 如果提供了现有的Windows窗体控件([System.Windows.Forms.Control]),则包装器将使用其余参数定义的属性和设置更新现有的Windows窗体控件。

-Member <HashTable>(位置1) 设置属性值,调用方法并在新对象或现有对象上添加事件。

  • 如果散列名称表示控件上的property,例如Size = "50, 50",该值将分配给控件属性值。
  • 如果散列名称表示控件上的method,例如Scale = {1.5, 1.5},将使用参数值调用控制方法。
  • 如果散列名称表示控件上的event,请参考例如Click = {$Form.Close()},值([ScriptBlock])将被添加到控制事件中。

两个集合属性ColumnStylesRowStyles特别针对TableLayoutPanel控件进行了简化,Grid控件被认为是WPF ColumnStyles控件的一般替代: - ColumnStyle属性,清除所有列宽并使用哈希值提供的RowStyles数组重置它们。 - RowStyle属性,清除所有行Heigth并使用散列值提供的[Void]$Control.Control.ColumnStyles.Add((New-Object Windows.Forms.ColumnStyle("Percent", 100))数组重置它们。 注意:如果要添加或插入单个特定的ColumnStyle或RowStyle项,则需要回退本机语句,例如:-Add <Array>

-Add -addparameter将一个或多个子控件添加到当前控件。 注意:如果容器通过管道输出到控件,则无法使用-Container <System.Windows.Forms.Control>参数。

$ParentContainer | Form $ChildControl(来自管道) 父容器通常由管道提供:-Set <HashTable>并将(新)子控件附加到相关容器。

-Set SetCellPositionparameter设置(SetColumnSetColumnSpanSetRowSetRowSpanSetStyleSet RowSpan = 2)与其父面板容器相关的特定子控件属性,例如, .-set 注意:以上是关于PowerShell Windows窗体包装器PowerShell表单控件包装器的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Windows 窗体在列表视图中显示 PowerShell 输出

powershell 使用Procrun将Java JAR包装到Windows服务中。

任务计划程序托管包装器不显示所有任务

允许 javascript 在 Windows 窗体 Web 浏览器上运行

PowerShell初探

任务计划的 Powershell 脚本不显示消息框