Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Building counter GUI using powershell

I have remaining Time of 20 sec. How can I create a PowerShell GUI that shows a countdown timer with an OK button? The timer should show the remaining time in decreasing order (e.g., 20, 19, 18) and should close automatically when the remaining time is complete. If the user clicks the OK button before the remaining time is complete, it should close the timer.

#Remaing time in seconds
$delay = 10

#Add assembly for windows forms
Add-Type -AssemblyName System.Windows.Forms

$Counter_Form = New-Object System.Windows.Forms.Form
$Counter_Form.Text = "Countdown Timer!"
$Counter_Form.Width = 450
$Counter_Form.Height = 200

$Counter_Label = New-Object System.Windows.Forms.Label
$Counter_Label.Width = 300
$Counter_Label.Height = 30
$Counter_Label.ForeColor = "Green"

$normalfont = New-Object System.Drawing.Font("Times New Roman", 14)
$Counter_Label.Font = $normalfont
$Counter_Label.Left = 20
$Counter_Label.Top = 20

$Counter_Form.Controls.Add($Counter_Label)


#Adding button so that that exist without waiting for counter to complete
$OK_Button = New-Object System.Windows.Forms.Button
$OK_Button.Text = "OK"
$OK_Button.Width = 100
$OK_Button.Height = 30
$OK_Button.Left = 20
$OK_Button.Top = 70
$OK_Button.Add_Click({
    #here closing the form but we can shut down the system also
    $Counter_Form.Close()
})
$Counter_Form.Controls.Add($OK_Button)



while ($delay -ge 0)
{
     
    $Counter_Form.Visible = $true
    $Counter_Label.Text = "Seconds Remaining: $($delay)"
    
    if ($delay -lt 5)
    { 
        $Counter_Label.ForeColor = "Red"
        $fontsize = 20 - $delay
        
        $warningfont = New-Object System.Drawing.Font("Times New Roman", $fontsize, ([System.Drawing.FontStyle]::Bold -bor [System.Drawing.FontStyle]::Underline))
        $Counter_Label.Font = $warningfont
    } 

    Start-Sleep 1
    $delay -= 1
}

$Counter_Form.Visible = $false

$Counter_Form.ShowDialog()

In above code I have added OK button but it's not working .

like image 896
Rabins Rai Avatar asked Sep 14 '26 20:09

Rabins Rai


1 Answers

You can use a Timer instance as Jimi recommended in comments and in its Tick event you can define the logic for each tick which is pretty much the same that what you have in your while loop.

Add-Type -AssemblyName System.Windows.Forms

# We need to use a reference type here (a hashtable in this case)
# so that the Timer event can update it from that scope
$delay = @{ Counter = 10 }

$Counter_Form = [System.Windows.Forms.Form]@{
    Text   = 'Countdown Timer!'
    Width  = 450
    Height = 200
}

$Counter_Label = [System.Windows.Forms.Label]@{
    Width     = 300
    Height    = 30
    ForeColor = 'Green'
    Font      = New-Object System.Drawing.Font('Times New Roman', 14)
    Left      = 20
    Top       = 20
    Text      = 'Hello world!'
}
$Counter_Form.Controls.Add($Counter_Label)

$OK_Button = [System.Windows.Forms.Button]@{
    Text   = 'OK'
    Width  = 100
    Height = 30
    Left   = 20
    Top    = 70
}

$OK_Button.Add_Click({
    # If we click OK, stop the timer!
    $timer.Stop()
    # And update the label
    $Counter_Label.Text = 'Everything good!'
    $Counter_Label.ForeColor = 'Green'
    $Counter_Label.Font = [System.Drawing.Font]::new('Times New Roman', 14)
})
$Counter_Form.Controls.Add($OK_Button)

# Create a Timer instance
$timer = [System.Windows.Forms.Timer]::new()
# With 1 second interval ticks
$timer.Interval = [timespan]::FromSeconds(1).TotalMilliseconds
$timer.Add_Tick({
    $text = 'Seconds remaining: {0}' -f $delay.Counter--
    # You can always troubleshoot using `Out-Host` here, remove it when done
    $text | Out-Host
    $Counter_Label.Text = $text

    if ($delay.Counter -eq -1) {
        # Send a Cancel Dialog, this will trigger the disposal of all resources
        $Counter_Form.DialogResult = 'Cancel'
    }

    if ($delay.Counter -lt 5) {
        $Counter_Label.ForeColor = 'Red'
        $Counter_Label.Font = [System.Drawing.Font]::new(
            'Times New Roman',
            20 - $delay.Counter,
            [System.Drawing.FontStyle]::Bold -bor [System.Drawing.FontStyle]::Underline)
    }
})

$Counter_Form.Add_Shown({
    $Counter_Form.Activate()
    $timer.Start()
})

# when exiting the form
if ($Counter_Form.ShowDialog()) {
    $timer.Dispose()

    $Counter_Form.Controls | ForEach-Object {
        $_.Dispose()
    }

    $Counter_Form.Dispose()
}
like image 121
Santiago Squarzon Avatar answered Sep 19 '26 02:09

Santiago Squarzon



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!