ui/progress-bar.psm1
|
Class ProgressBar { [string]$Label [bool]$canStop [int]$ThrottlePercent # minimum UI update interval in percents [System.Windows.Forms.Form]$MainForm [bool]$IsCanceled [int]$CurrentValue = 0 [int]$Total = 0 [float]$LastPercent = 0 [System.Windows.Forms.Form]$ProgressForm [System.Windows.Forms.ProgressBar]$ProgressBar [System.Windows.Forms.Label]$PercentLabel ProgressBar([System.Windows.Forms.Form]$mainForm, [int]$Total) { $this.MainForm = $MainForm $this.Total = $Total $this.Label = "Please wait..." $this.canStop = $false $this.ThrottlePercent = 5 $this.Start() } ProgressBar([System.Windows.Forms.Form]$mainForm, [int]$Total, [string]$Label = "Please wait...") { $this.MainForm = $MainForm $this.Total = $Total $this.Label = $Label $this.canStop = $false $this.ThrottlePercent = 5 $this.Start() } ProgressBar([System.Windows.Forms.Form]$mainForm, [int]$Total, [string]$Label = "Please wait...", [boolean]$canStop = $false) { $this.MainForm = $MainForm $this.Total = $Total $this.Label = $Label $this.canStop = $canStop $this.ThrottlePercent = 5 $this.Start() } ProgressBar([System.Windows.Forms.Form]$mainForm, [int]$Total, [string]$Label = "Please wait...", [boolean]$canStop = $false, [int]$ThrottlePercent = 5) { $this.MainForm = $MainForm $this.Total = $Total $this.Label = $Label $this.canStop = $canStop $this.ThrottlePercent = $ThrottlePercent $this.Start() } [void]Start() { # Create form $formHeight = if ($this.canStop) { 120 } else { 90 } $this.ProgressForm = New-Object System.Windows.Forms.Form $this.ProgressForm.Tag = $this $this.ProgressForm.Text = "" $this.ProgressForm.Size = New-Object System.Drawing.Size(300, $formHeight) $this.ProgressForm.StartPosition = [System.Windows.Forms.FormStartPosition]::Manual $this.ProgressForm.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::FixedDialog $this.ProgressForm.ControlBox = $false $this.ProgressForm.ShowInTaskbar = $false $this.ProgressForm.Top = $this.mainForm.Top + [int](($this.mainForm.Height - $this.ProgressForm.Height) / 2) $this.ProgressForm.Left = $this.mainForm.Left + [int](($this.mainForm.Width - $this.ProgressForm.Width) / 2) $this.ProgressForm.add_FormClosed({ param($s, $e) $self = $s.Tag $self.mainForm.WindowState = [System.Windows.Forms.FormWindowState]::Normal $self.mainForm.Activate() }) # Progress label $progressLabel = New-Object System.Windows.Forms.Label $progressLabel.AutoSize = $true $progressLabel.Location = New-Object System.Drawing.Point(20, 15) $progressLabel.Text = $this.Label # ProgressBar $this.ProgressBar = New-Object System.Windows.Forms.ProgressBar $this.ProgressBar.Minimum = 0 $this.ProgressBar.Maximum = 100 $this.ProgressBar.Value = 0 $this.ProgressBar.Step = 1 $this.ProgressBar.Style = "Continuous" $this.ProgressBar.Size = New-Object System.Drawing.Size(260, 20) $this.ProgressBar.Location = New-Object System.Drawing.Point(20, 35) # Percent label $this.percentLabel = New-Object System.Windows.Forms.Label $this.percentLabel.AutoSize = $true $this.percentLabel.Location = New-Object System.Drawing.Point(130, 60) $this.percentLabel.Text = "0 %" # Cancel button if ($this.canStop) { $btnStop = New-Object System.Windows.Forms.Button $btnStop.Text = "Cancel" $btnStop.Width = 80 $btnStop.Height = 25 $btnStop.Location = New-Object System.Drawing.Point(($this.ProgressBar.Right - $btnStop.Width), ($this.ProgressForm.Height - $btnStop.Height - 20)) $btnStop.Add_Click({ param($s, $e) $self = $s.Parent.Tag $self.IsCanceled = $true $s.Text = "Cancelling..." $s.Enabled = $false }) $this.ProgressForm.Controls.Add($btnStop) } $this.ProgressForm.Controls.Add($progressLabel) $this.ProgressForm.Controls.Add($this.ProgressBar) $this.ProgressForm.Controls.Add($this.percentLabel) $this.mainForm.Enabled = $false $this.ProgressForm.Show($this.mainForm) $this.ProgressForm.Refresh() } [void]Update([int]$Value) { $this.CurrentValue = $Value if ($this.Total -eq 0) { return } $percent = [math]::Round(($this.CurrentValue / $this.Total) * 100) if ($percent -gt 100) { $percent = 100 } if (-not $this.LastPercent) { $this.LastPercent = 0 } # Refresh only if moved at least $ThrottlePercent or reached the end if (($percent - $this.LastPercent) -ge $this.ThrottlePercent -or $percent -eq 100) { $this.ProgressBar.Value = $percent $this.PercentLabel.Text = "$percent %" [System.Windows.Forms.Application]::DoEvents() $this.LastPercent = $percent } } [void]close() { #WORKAROUND: Invoke on UI thread, because if simple Close() is called then main form minimizes $this.ProgressForm.BeginInvoke( [Action[System.Windows.Forms.Form, System.Windows.Forms.Form]] { param($progressForm, $mainForm) if ($progressForm -and -not $progressForm.IsDisposed) { $mainForm.Enabled = $true $progressForm.Close() $progressForm.Dispose() } }, @($this.ProgressForm, $this.mainForm) ) } } |