In my last Friday Fun post, I shared some PowerShell code for displaying [System.Drawing.Color] values from a console using ANSI escape sequences. After I published the article, I realized what I really wanted was a color palette display that wouldn't be affected by the console background. A Windows Presentation Foundation (WPF) form would do the trick. I could use the form to display a color sample. WPF is a handy technique for displaying information, and it doesn't have to involve complex XAML files.
ManageEngine ADManager Plus - Download Free Trial
Exclusive offer on ADManager Plus for US and UK regions. Claim now!
Start Simple
I often create PowerShell scripts to generate WPF output that doesn't rely on XAML files. For simple displays, you can accomplish everything with PowerShell code. The first step in any WPF project is to add the required assembly.
Add-Type -AssemblyName PresentationFramework
I first wrote some proof-of-concept code to display a single color. Eventually, I knew I wanted to display the entire color palette. Focusing on showing a single color would identify potential problems or gaps in my WPF knowledge, which I know there are plenty of.
The first step is to define the window form.
$form = New-Object System.Windows.Window
$form.Title = "Color Sample"
$form.Height = 100
$form.Width = 300
$form.top = 200
$form.left = 100
$form.UseLayoutRounding = $True
$form.WindowStartupLocation = "CenterScreen"
The property names should be self-explanatory. With WPF, the controls, such as buttons and textboxes, have to live inside a container, not to be confused with a Docker container. For simple WPF forms, I often use a Stack Panel.
$stack = New-Object System.Windows.Controls.StackPanel
I think of this as a series of shelves. Each control that I add to the stack is layered in order. My stack only needs a TextBox.
$TextBox = New-Object System.Windows.Controls.TextBox
$TextBox.Width = 275
$textbox.Height = 30
$TextBox.HorizontalAlignment = "Center"
$textbox.TextAlignment = "center"
$textbox.VerticalContentAlignment = "center"
$textbox.FontSize = 16
By the way, I realize you may not be familiar with all of a particular control's properties. No problem. You can use Get-Member.
$TextBox | Get-Member
I want to set the textbox background to the specified color and the textbox text to show the color name and RGB values. Here's where I hit my first hurdle.
The Background property is expecting an object type of [System.Windows.Media.Brush].
I intend to provide a name value.
$color = "cornsilk"
I know I can get the [System.Drawing.Color] object from this value.
$sdc = [System.Drawing.Color]::FromName($color)
But that is a different object type. After a little online research and learning more about WPF, I discovered the [System.Windows.Media.BrushConverter] class. I could use this to convert colors to the [System.Windows.Media.Brush] class. The converter has a ConvertFromString() method. The parameter is an HTML color string such as #FFF8DC I have the RGB values from [System.Drawing.Color]. How do I convert them to the HTML string?
Once again, I learned something new. I have never paid any attention to HTML color codes. I knew how to use them but never considered how they were constructed. Here's an example of why I think it is essential to understand why PowerShell behaves and not merely regurgitate a command. I discovered that the HTML code is the RGB value converted to hex. That I can do.
The format string is case-sensitive, so be sure to use X. The 2 indicates format to two places, which is important when formatting zero values. With this in mind, I can convert values and set the TextBox properties.
$htmlcode = "#{0:X2}{1:X2}{2:X2}" -f $sdc.r, $sdc.g, $sdc.b
$textbox.background = [System.Windows.Media.BrushConverter]::new().ConvertFromString($htmlcode)
$name = $sdc.Name
$TextBox.Text = "$name ($($sdc.R),$($sdc.G),$($sdc.B))"
All that remains is to add the Textbox to the stack, add the stack to the form, and display the form.
$stack.AddChild($TextBox)
$form.AddChild($stack)
[void]$form.ShowDialog()
Be sure to use the ShowDialog() method and not Show(). The ShowDialog() method returns a Boolean value that I rarely need to see, so I cast the output to [Void]. Your PowerShell prompt will be blocked until you close the form.
I didn't add a button to the form. I click the X to close the window.
Show-SingleColor
I wrapped all of my code into a PowerShell function. Remember to include the Add-Type command in the script file.
Function Show-SingleColor {
Param([string]$Color)
$form = New-Object System.Windows.Window
$form.Title = "Color Sample"
$form.Height = 100
$form.Width = 300
$form.top = 200
$form.left = 100
$form.UseLayoutRounding = $True
$form.WindowStartupLocation = "CenterScreen"
$stack = New-Object System.Windows.Controls.StackPanel
$TextBox = New-Object System.Windows.Controls.TextBox
$TextBox.Width = 275
$textbox.Height = 30
$TextBox.HorizontalAlignment = "Center"
$textbox.TextAlignment = "center"
$textbox.VerticalContentAlignment = "center"
$textbox.FontSize = 16
#The drawing color may need to be converted to a brush color
#convert color to html value
$sdc = [System.Drawing.Color]::FromName($color)
#get RGB values and convert to HTML
$htmlcode = "#{0:X2}{1:X2}{2:X2}" -f $sdc.r, $sdc.g, $sdc.b
$textbox.background = [System.Windows.Media.BrushConverter]::new().ConvertFromString($htmlcode)
$name = $sdc.Name
$TextBox.Text = "$name ($($sdc.R),$($sdc.G),$($sdc.B))"
$stack.AddChild($TextBox)
$form.AddChild($stack)
[void]$form.ShowDialog()
}
This function is a handy tool when I only need to see a single color, which I may still want. The actual value of my code was serving as a testbed and laying the foundation for more complex WPF and PowerShell functions. I'll dive into those next time.
2 thoughts on “More Colorful Fun with PowerShell”
Comments are closed.