Friday fun: Create a WPF Clock Widget with PowerShell

The guys over at Arction have kindly made available a free Gauge control for WPF. I decided to download it and create a clock using PowerShell. The result is New-WPFClock.

Clock

To use the function, first download the free Gauge control. You’ll find the Arction.WPF.Gauges.dll in the Libs\Wpf folder. In the script on line 26, enter the location of this dll on your system.

Then simply call New-WPFClock.

The function has a couple of optional parameters:

  • Color – set the colour of the clock face
  • Height – set the height
  • Width – set the width
  • FontSize – set the size of the numbers
  • AlwaysOnTop – keep the clock on top of other windows

To close the clock, simply right-click it.

Enjoy!

Function New-WPFClock {
## Generates a clock displaying the current system time
## Requires the Arction WPF Gauges, a free download from https://www.arction.com/free-gauges/
## Set the location of the Arction Gauges dll on line 26
[CmdletBinding()]
Param
(
[Parameter(Mandatory=$false,Position=0)]
$Color = "SteelBlue",
[Parameter(Mandatory=$false,Position=1)]
[int]$Height = 300,
[Parameter(Mandatory=$false,Position=2)]
[int]$Width = 300,
[Parameter(Mandatory=$false,Position=3)]
[int]$FontSize = 30,
[Parameter(Mandatory=$false,Position=4)]
[switch]$AlwaysOnTop
)
# Load the required assemblies
Add-Type -AssemblyName PresentationFramework,PresentationCore
Try
{
Add-Type -Path "<path>\Arction.WPF.Gauges.dll" -ErrorAction Stop
}
Catch
{
$e = New-Object 'System.IO.FileLoadException' "Could not add the Arction.WPF.Gauges.dll. Ensure it is available"
$Category = [System.Management.Automation.ErrorCategory]::ObjectNotFound
$TargetObject = ""
$errorRecord = New-Object System.Management.Automation.ErrorRecord $e, $errorID, $Category, $TargetObject
$PSCmdlet.ThrowTerminatingError($errorRecord)
}
# Create the window
$Window = [System.Windows.Window]::new()
$Window.SizeToContent = [System.Windows.SizeToContent]::WidthAndHeight
$Window.AllowsTransparency = $true
$Window.Background = "Transparent"
$Window.WindowStyle = "None"
$Window.WindowStartupLocation = "CenterScreen"
If ($AlwaysOnTop)
{
$Window.Topmost = $true
}
# Create the Gauge
$Gauge = [Arction.Gauges.Gauge]::new()
$Gauge.Margin = 5
$Gauge.Height = $Height
$Gauge.Width = $Width
$Gauge.Fill = $Color
$Gauge.FontSize = $FontSize
$Gauge.Cursor = "Hand"
# Allow drag
$Gauge.Add_MouseLeftButtonDown({
$Window.DragMove()
})
# Close on right-click
$Gauge.Add_MouseRightButtonUp({
$Window.Close()
})
# Create the Hour Scale
$HourScale = New-object Arction.Gauges.Scale
$HourScale.AngleBegin = 60
$HourScale.AngleEnd = 60
$HourScale.RangeBegin = 1
$HourScale.RangeEnd = 13
$HourScale.Theme = "None"
$HourScale.MajorTickCount = 12
$HourScale.MinorTickCount = 0
$HourScale.TertiaryTickCount = 0
$HourScale.DialShape = [Arction.Gauges.Dials.DialShape]::DefaultNeedle
$HourScale.DialLengthFactor = 0.6
$HourScale.DialColor1 = "White"
$HourScale.Label = [System.Windows.Controls.TextBlock]::new()
$HourScale.ValueIndicator.Foreground = $Color
$HoursMajorTicks = New-Object Arction.Gauges.MajorTicksLine
$HoursMajorTicks.LabelOffset = -12
$HoursMajorTicks.OffsetA = -5
$HoursMajorTicks.TickThickness = -5
$HoursMajorTicks.FontWeight = "Bold"
$HoursMajorTicks.FontFamily = "Arial"
$HoursMajorTicks.TickStroke = "White"
$HoursMajorTicks.LabelBrush = "White"
$HourScale.MajorTicks = $HoursMajorTicks
# Create the Minute Scale
$MinuteScale = New-object Arction.Gauges.Scale
$MinuteScale.AngleBegin = 90
$MinuteScale.AngleEnd = 90
$MinuteScale.RangeBegin = 0
$MinuteScale.RangeEnd = 60
$MinuteScale.Theme = "None"
$MinuteScale.MajorTickCount = 60
$MinuteScale.MinorTickCount = 0
$MinuteScale.TertiaryTickCount = 0
$MinuteScale.DialShape = [Arction.Gauges.Dials.DialShape]::DefaultNeedle
$MinuteScale.DialLengthFactor = 0.8
$MinuteScale.DialColor1 = "White"
$MinutesMajorTicks = New-Object Arction.Gauges.MajorTicksLine
$MinutesMajorTicks.OffsetA = -4
$MinutesMajorTicks.OffsetB = -2
$MinutesMajorTicks.TickThickness = 2
$MinutesMajorTicks.LabelFormat = ""
$MinutesMajorTicks.TickStroke = "White"
$MinutesMajorTicks.LabelBrush = "White"
$MinuteScale.MajorTicks = $MinutesMajorTicks
# Create the Seconds Scale
$SecondsScale = New-object Arction.Gauges.Scale
$SecondsScale.AngleBegin = 90
$SecondsScale.AngleEnd = 90
$SecondsScale.RangeBegin = 0
$SecondsScale.RangeEnd = 60
$SecondsScale.Theme = "None"
$SecondsScale.MajorTickCount = 60
$SecondsScale.MinorTickCount = 0
$SecondsScale.TertiaryTickCount = 0
$SecondsScale.DialShape = [Arction.Gauges.Dials.DialShape]::Line
$SecondsScale.DialLengthFactor = 0.8
$SecondsDial = New-Object Arction.Gauges.Dials.Dial
$SecondsDial.MaxWidth = 5
$SecondsDial.Height = 28
$SecondsDial.AspectRatio = 0.2
$SecondsScale.Dial = $SecondsDial
$SecondsMajorTicks = New-Object Arction.Gauges.MajorTicksLine
$SecondsMajorTicks.OffsetA = -4
$SecondsMajorTicks.OffsetB = -2
$SecondsMajorTicks.TickThickness = 2
$SecondsMajorTicks.LabelFormat = ""
$SecondsMajorTicks.TickStroke = "White"
$SecondsMajorTicks.LabelBrush = "White"
$SecondsScale.MajorTicks = $SecondsMajorTicks
# Add the scales to the Gauge
$Gauge.PrimaryScale = $HourScale
$Gauge.SecondaryScales.Add($MinuteScale)
$Gauge.SecondaryScales.Add($SecondsScale)
# Add the Gauge to the window
$Window.AddChild($Gauge)
# Set the initial time values
$Gauge.PrimaryScale.Value = [System.DateTime]::Now.Hour
$Gauge.SecondaryScales[0].Value = [System.DateTime]::Now.Minute
$Gauge.SecondaryScales[1].Value = [System.DateTime]::Now.Second
# Start a dispatcher timer to update the clock every second
$TimerCode = {
$Gauge.PrimaryScale.Value = [System.DateTime]::Now.Hour
$Gauge.SecondaryScales[0].Value = [System.DateTime]::Now.Minute
$Gauge.SecondaryScales[1].Value = [System.DateTime]::Now.Second
}
$DispatcherTimer = New-Object -TypeName System.Windows.Threading.DispatcherTimer
$DispatcherTimer.Interval = [TimeSpan]::FromSeconds(1)
$DispatcherTimer.Add_Tick($TimerCode)
$DispatcherTimer.Start()
# Activate the window on load
$Window.Add_Loaded({
$This.Activate()
})
# Stop the dispatcher on close
$Window.Add_Closed({
$DispatcherTimer.Stop()
})
# Display the window
$null = $window.Dispatcher.InvokeAsync{$window.ShowDialog()}.Wait()
}

view raw
New-WPFClock
hosted with ❤ by GitHub