在Powershell中继承Form属性(Label,GroupBox等)

时间:2018-10-13 20:19:12

标签: powershell

我正在Powershell中寻找继承。我的Windows表单中有很多标签,groupBoxes,dropDowns等,例如:

$amuletLabelValueDmg = New-Object System.Windows.Forms.Label
$amuletLabelValueDmg.Location = New-Object System.Drawing.Size(10,20) 
$amuletLabelValueDmg.Size = New-Object System.Drawing.Size(60,20) 
$amuletLabelValueDmg.Text = 'Value'
$groupBoxAmulet.Controls.Add($amuletLabelValueDmg)

$amuletLabelHealth = New-Object System.Windows.Forms.Label
$amuletLabelHealth.Location = New-Object System.Drawing.Size(10,40) 
$amuletLabelHealth.Size = New-Object System.Drawing.Size(60,20) 
$amuletLabelHealth.Text = 'Health'
$groupBoxAmulet.Controls.Add($amuletLabelHealth)

$amuletLabelResistance = New-Object System.Windows.Forms.Label
$amuletLabelResistance.Location = New-Object System.Drawing.Size(10,60) 
$amuletLabelResistance.Size = New-Object System.Drawing.Size(60,20) 
$amuletLabelResistance.Text = 'Resistance'
$groupBoxAmulet.Controls.Add($amuletLabelResistance)

在这种情况下,我正在寻找Label的继承关系(或者您可以将自己的图片显示为groupBox或dropDown而不是label,princip相同)。我不想复制,粘贴Labels的hundreads,我想使用继承,而只是使用参数调用某些Class。

我尝试使用函数,但是很快我意识到我将永远只有一个实例,因此这将无法工作。我的朋友建议我在Powershell中使用Class之类的东西,而不是上面的那些行,只需用新实例调用该类。但是我有点迷茫。有人知道如何“复制”很多标签吗?我想象这样的解决方案:

class labelValueDmg {
    variables and definition of label 
}

$amuletLabelValueDmg = New-Object labelValueDmg
$beltLabelValueDmg = New-Object labelValueDmg

powershell中是否有类似的东西,或者您将如何解决此问题?如果您有50个标签,50个boxBoxes等...

[1]实际上,我找到了另一种解决方法。据我所知,您可以使用一个简单的函数来执行此操作。而且更有效。我这样声明函数>>

function createNewObject {
    param (
        [int[]] $Location,
        [int[]] $Size,
        [string] $Type,
        [string] $Text
    )

   if ($Type -eq 'Label') { $newObject = New-Object System.Windows.Forms.Label }
   elseif ($Type -eq 'TextBox') { $newObject = New-Object System.Windows.Forms.TextBox }
   elseif ($Type -eq 'CheckBox') { $newObject = New-Object System.Windows.Forms.CheckBox }
   elseif ($Type -eq 'Button') { $newObject = New-Object System.Windows.Forms.Button }
   elseif ($Type -eq 'GroupBox') { $newObject = New-Object System.Windows.Forms.GroupBox }
   elseif ($Type -eq 'RadioButton') { $newObject = New-Object System.Windows.Forms.RadioButton }

   $newObject.Location = New-Object System.Drawing.Size $Location[0], $Location[1]
   $newObject.Size = New-Object System.Drawing.Size $Size[0], $Size[1]
   $newObject.Text = $Text

   return $newObject
}

然后我将使用新变量调用此函数,例如>>

$amuletLabelValueDmg = createNewObject(20,10) (40,10) 'Label' 'Value'
$cloakTextBox = createNewObject(40,10) (40,10) 'TextBox' 'Cloak'

我认为这是仅用变量$ Type调用一个函数的好方法,其中我决定对象是标签,文本框还是其他对象。 毕竟,感谢您的代码,我以形式展示了对象。

$objForm.Controls.AddRange(@(
    $amuletLabelValueDmg
    $cloakTextBox
))

据我所知,这是解决我的问题的非常方便的方法。

2 个答案:

答案 0 :(得分:1)

您可以使用以下技术显着减少代码中的“噪音”和重复性,该技术不需要继承/类型扩展 [1]


New-Object-Property参数一起使用,您可以向其传递属性的 hashtable ,从而避免了先创建变量然后必须分别分配属性:

$amuletLabelValueDmg = New-Object Windows.Forms.Label -Property @{
  Location = New-Object Drawing.Point 10, 20
  Size = New-Object Drawing.Size 60, 20
  Text = 'Value'
}
$groupBoxAmulet.Controls.Add($amuletLabelValueDmg)

注意:

  • 我通过从类型名称中省略System.前缀来进一步缩短了代码,在PowerShell中通常是 optional Add-Type,{ {1}}和Update-TypeData调用以及Update-FormatDatausing assembly语句)。

  • 顺便说一句:请注意我如何更改某些using namespace调用的语法,例如Drawing.Size(60,20)New-Object New-Object Drawing.Size 60, 20 to(60,20). The no-whitespace 60,20 syntax should be avoided, because it is based on mistaking the syntax for a _method call_, which it isn't:-ArgumentList`参数;参数传递时不带括号,由空格分隔。


PSv5 + 中,您可以使用 casts 静态is an array _argument_ that is bound to the (implied)方法代替类型{{1 }},以及 ::new()语句以缩短类型名称

New-Object

无论哪种情况,您都可以创建简单的函数包装器(为简便起见,在此处使用PSv5 +;可以并且应该使该函数更健壮):

using namespace

最后,您可以通过将数组文字传递到容器控件的# Load the System.Windows.Forms assembly # which implicitly loads System.Drawing too. using assembly System.Windows.Forms # Declare implied namespaces, so that types from # the loaded assemblies can be referred to by mere name # (e.g., 'Form' instead of 'System.Windows.Forms') using namespace System.Windows.Forms using namespace System.Drawing $amuletLabelValueDmg = [Label] @{ Location = [Point]::new(10, 20) Size = [Size]::new(60, 20) Text = 'Value' } $groupBoxAmulet.Controls.Add($amuletLabelValueDmg) 方法(假设存在上面定义的function New-Label { param( [int[]] $Location, [int[]] $Size, [string] $Text ) # Create and output a new label control [Label] @{ Location = [Point]::new($Location[0], $Location[1]) Size = [Size]::new($Size[0], $Size[1]) Text = $Text } } $amuletLabelValueDmg = New-Label 10,20 60,20 Value 函数)来减少对辅助变量的需求:

Controls.AddRange()

[1]虽然我个人认为这不值得,但如果您确实想通过继承/类型扩展来做到这一点,则必须附加自定义控件创建代码而不是单独的实例(请注意,New-Label只会使控件类型对象 (例如 $groupBoxAmulet.Controls.AddRange(@( New-Label 10,20 60,20 Value New-Label 10,40 60,20 Health New-Label 10,60 60,20 Resistance )) )(例如[System.Windows.Forms.Label]已经存在的实例上可用的新定义成员。

Update-TypeData -TypeName System.Windows.Forms.Label ...

答案 1 :(得分:-1)

您可以创建custom object并添加methods,这些设置将以您需要的方式设置通用属性。像这样:

$Label = New-Object System.Windows.Forms.Label

Add-Member -MemberType ScriptMethod `
           -InputObject $Label `
           -Name 'Value' `
           -Value {
                $This.Location = New-Object System.Drawing.Size(10,20) 
                $This.Size = New-Object System.Drawing.Size(60,20)
                $This.Text = 'Value'
                return $This
            } -Force

Add-Member -MemberType ScriptMethod `
           -InputObject $Label `
           -Name 'Health' `
           -Value {
                $This.Location = New-Object System.Drawing.Size(10,40) 
                $This.Size = New-Object System.Drawing.Size(60,20)
                $This.Text = 'Health'
                return $This
            } -Force

Add-Member -MemberType ScriptMethod `
           -InputObject $Label `
           -Name 'Resistance' `
           -Value {
                $This.Location = New-Object System.Drawing.Size(10,60) 
                $This.Size = New-Object System.Drawing.Size(60,20)
                $This.Text = 'Resistance'
                return $This
            } -Force


$Value = $Label.Value()
$Health = $Label.Health()
$Resistance = $Label.Resistance()