Search code examples
powershell

PowerShell - Get Reference to an dynamic created button


I have the Following Script:

$ButtonList = @{
    'NumPad1' = "Enter"
    'NumPad2'  = "ESC"
}


function WriteButtonName ($sBName){
    Write-Host $sBName
    
}


$x_pos= 35

$v= get-variable -Name "x_pos"
$($v.Name)


$form = New-Object System.Windows.Forms.Form
foreach($b in $ButtonList.GetEnumerator()){
$Name = $($b.Name) 
$Value = $($b.Value)
$Name
$Value
    Remove-Variable -Name $Name
    New-Variable -Name $Name #-Value New-Object System.Windows.Forms.Button
    (get-variable -Name $Name).Value = New-Object System.Windows.Forms.Button
    (get-variable -Name $Name).Value.Location = New-Object System.Drawing.Size($x_pos,35)
    (get-variable -Name $Name).Value.Size = New-Object System.Drawing.Size(120,23)
    (get-variable -Name $Name).Value.Text = $Value
    (get-variable -Name $Name).Value.Add_Click({WriteButtonName -sBName (get-variable -Name $Name).Value.Text })

$x_pos += 130
$form.Controls.Add((get-variable -Name $Name).Value)
}

$form.showdialog()

This Scipt Create 2 Buttons, and by Clicking they return Something. But because in '$Name' is stored just the last Name I didn't get the Name from the Varible where the first Button is stored.

How can I get NUMPAD1 by click the first button.

Thanks.


Solution

  • You're making this way more complicated than need be, and by using both New-Variable and Remove-Variable within the same loop, you will be indeed left with the name and value of the last button in the iteration.

    Just do:

    # if you want to keep this order when creating the buttons, use [ordered]@{ .. } instead
    $ButtonList = @{
        'NumPad1' = 'Enter'
        'NumPad2' = 'ESC'
    }
    
    $form = New-Object System.Windows.Forms.Form
    #left start position of first button
    $x_pos= 20
    foreach($b in $ButtonList.GetEnumerator()){
        $button = New-Object System.Windows.Forms.Button
        $button.Name = $b.Name
        $button.Text = $b.Value
        $button.Size = New-Object System.Drawing.Size 120,23
        $button.Location = New-Object System.Drawing.Point $x_pos, 35
        $button.Add_Click({ Write-Host $this.Text})  # use $this.Name if you want to see 'NumPad1' or 'NumPad2'
    
        $x_pos += 125
        $form.Controls.Add($button)
    }
    
    $form.ShowDialog()
    
    # don't forget to remove the form from memory when all done
    $form.Dispose()
    

    P.S. Within the scriptblock for the Click event, you can reference the current control using the $this Automatic variable