0

I am struggling with an until loop in combination with a random picker and a mouse click in a PowerShell Form.

I am able to run a random picker without the form , where I have weekdays, picked by random and one by one day, is being removed, until the arraylist is empty. Works not bad.

$Weekdays = 'Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday'

[System.Collections.ArrayList]$arraylist = $Weekdays

Write-Host $arraylist -ForegroundColor Green
pause
do {
    $removetask = Get-Random $arraylist.ToArray()
    $arraylist.Remove($removetask)
    Write-Host $removetask
    Write-Host $arraylist -ForegroundColor Red
    pause
} until ($arraylist.Count -eq 0)

In another approach, I tried to do the same, but this time, I want to control the looping itself, that as soon as the first key from the arraylist is taken and shown in a label, I have to click the mouse button, so it continues to take the next random.

Without the do {} until () I got so far:

$TestForm = New-Object System.Windows.Forms.Form
$TestForm.Size = New-Object System.Drawing.Size (1200,800)
$TestForm.Text ='Random Test'
$TestForm.StartPosition = "CenterScreen"
$TestForm.AutoSize = $true
$TestForm.BringToFront()
$TestForm.BackgroundImageLayout = "Stretch"

[System.Collections.ArrayList]$Weekdays = 'Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday'

$TestLabel = New-Object System.Windows.Forms.label
$TestLabel.Location = New-Object System.Drawing.Size '500,200'
$TestLabel.Size = New-Object System.Drawing.Size '600,60'
$TestLabel.Font = New-Object System.Drawing.Font ('Times New Roman','20',[System.Drawing.FontStyle]::Bold)
$TestLabel.BackColor = 'Transparent'
$TestLabel.ForeColor = "Blue"
$removetask = Get-Random $Weekdays.ToArray()
$TestLabel.Text = $removetask
$TestForm.Controls.Add($TestLabel)

$TestButton = New-Object System.Windows.Forms.Button
$TestButton.Location = New-Object System.Drawing.Size '500,600'
$TestButton.Size = New-Object System.Drawing.Size '200,75'
$TestButton.Font = New-Object System.Drawing.Font ('Arial','10',[System.Drawing.FontStyle]::Bold)
$TestButton.Text = 'Next Random'
$TestForm.Controls.Add($TestButton)

$TestButton.Add_Click()

$TestForm.ShowDialog()
$TestForm.Dispose()

Now I have a few lines of code left, I am not able to include on such way, so it works on the following way.

The testform opens, and in a label I see chosen by random one of the weekdays. Clicking next will remove the chosen weekday from the arraylist and show the next weekday by random and will continue until the arraylist is empty.

The missing pieces to the puzzle are:

### The loop itself
do {} until ()

### code to find a Random value from $weekdays and write it into $removetask
$removetask = Get-Random $Weekdays.ToArray()

### code to remove the randomly chosen day and remove it from the arraylist
$Weekdays.Remove($removetask) 

#### check if array is empty
($weekdays.Count -eq 0)

I was playing around with the codes and tried with Button.Add_Click() and also with ButtonClickEvent {} but either, the loop is not running, the counter is not working correctly or I somehow messed up the code on such way, that it is stuck somewhere, that not even the form is being shown.

Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
Mike
  • 134
  • 4
  • 12
  • Running loops in forms is always problematical. Can you not just do everything in the click event? Test if the array is empty every time the mouse is clicked? – Scepticalist Sep 02 '19 at 19:33
  • It is true, it can be tricky. But I think, there is the possibility, to use if conditions instead and on such way, I might will be able to overcome this issue and build it into a click event. I surely will try it on such way. Thank you for trying – Mike Sep 02 '19 at 19:37

1 Answers1

0

The following enhanced adjustment of your script implements some kind of a loop in the form.

Note that no loop keywords (like do, while, until) and even no if keyword are used:

### Load Assemblies for creating form & controls ###
if ( -not ("System.Windows.Forms.Form" -as [type]) ) {
    Add-Type -AssemblyName System.Windows.Forms
}
if ( -not ("System.Drawing.Font" -as [type]) ) {
    Add-Type -AssemblyName System.Drawing
}

$TestForm = New-Object System.Windows.Forms.Form
$TestForm.Size = New-Object System.Drawing.Size (1200,800)
$TestForm.Text ='Random Test'
$TestForm.StartPosition = "CenterScreen"
$TestForm.AutoSize = $true
$TestForm.BringToFront()
$TestForm.BackgroundImageLayout = "Stretch"

$TestLabel = New-Object System.Windows.Forms.label
$TestLabel.Location = New-Object System.Drawing.Size '500,200'
$TestLabel.Size = New-Object System.Drawing.Size '600,60'
$TestLabel.Font = New-Object System.Drawing.Font ('Times New Roman','20',[System.Drawing.FontStyle]::Bold)
$TestLabel.BackColor = 'Transparent'
$TestLabel.ForeColor = "Blue"
$TestForm.Controls.Add($TestLabel)

$TestLabe2 = New-Object System.Windows.Forms.Label
$TestLabe2.Location = New-Object System.Drawing.Size '200,300'
$TestLabe2.Size = New-Object System.Drawing.Size '900,200'
$TestLabe2.Font = New-Object System.Drawing.Font ([System.Windows.Forms.Label]::DefaultFont.Name,'16',[System.Drawing.FontStyle]::Italic)
$TestLabe2.BackColor = 'Transparent'
$TestLabe2.ForeColor = [System.Drawing.Color]::MidnightBlue
$TestForm.Controls.Add($TestLabe2)

$TestButton = New-Object System.Windows.Forms.Button
$TestButton.Location = New-Object System.Drawing.Size '500,600'
$TestButton.Size = New-Object System.Drawing.Size '200,75'
$TestButton.Font = New-Object System.Drawing.Font ('Arial','10',[System.Drawing.FontStyle]::Bold)
$TestButton.Text = 'Next Random'
$TestForm.Controls.Add($TestButton)

$TestButtoX = New-Object System.Windows.Forms.Button
$TestButtoX.Location = New-Object System.Drawing.Size '200,600'
$TestButtoX.Size = New-Object System.Drawing.Size '200,75'
$TestButtoX.Font = New-Object System.Drawing.Font ('Arial','10',[System.Drawing.FontStyle]::Bold)
$TestButtoX.Text = 'Next Round'
$TestButtoX.Enabled = $false
$TestForm.Controls.Add($TestButtoX)

Function Swap-Buttons {
    $TestButton.Enabled =      [bool]$script:Weekdays.Count
    $TestButtoX.Enabled = -not [bool]$script:Weekdays.Count
}

Function RemoveWeekday {
    $script:removetask = Get-Random $script:Weekdays.ToArray()
    $script:Weekdays.Remove($script:removetask)
    $TestLabe2.Text = ('(remain {0})' -f $script:Weekdays.Count), ($script:Weekdays -join ', ') -join ':   '
    $TestLabel.Text = $script:removetask
    Swap-Buttons
}

Function DefineWeek {
    $script:Weekdays = [System.Collections.ArrayList]([System.Enum]::GetNames([System.DayOfWeek]))
    <#
    # debugging: try another array list (a larger one)
    $script:Weekdays = [System.Collections.ArrayList]([System.Drawing.Color] |
        Get-Member -MemberType Properties -Static -Force |
            Where-Object Name -match ".+blue"  |
            Select-Object -ExpandProperty Name
    )
    <##>
}

$TestButton.Add_Click({
    RemoveWeekday
})

$TestButtoX.Add_Click({
    DefineWeek
    $TestButtoX.Enabled = $false 
    $TestButton.Enabled = $true
    RemoveWeekday
})

$script:removetask = ''
DefineWeek
RemoveWeekday

$TestForm.ShowDialog()
$TestForm.Dispose()
JosefZ
  • 28,460
  • 5
  • 44
  • 83