Font Dialog Selection using PowerShell

While I was working on an update to my PoshChat project, one of the requests that I had was to allow for font size changes on the client UI. I wanted the user to have the capability to not only select the size, but also to have other options such as bold text, font style, etc… In order to make this happen, I needed some sort of UI to allow the user to make these changes. Sounds like a lot of work was ahead of me, but after some looking on the MSDN site, I was able to find exactly what I was looking for: windows.forms.fontdialog.

Using this UI, I am not able to bring up a selection dialog for a user to pick what they would like.

Add-Type -AssemblyName System.Windows.Forms
$fontDialog = new-object windows.forms.fontdialog
$fontDialog.Showcolor = $True
$fontDialog.FontMustExist = $True
$fontDialog.ShowDialog()

image

You may have noticed that I specified some options to allow the use of colors and also to ensure that only the fonts that exist on the computer it was run on actually exist. You can limit what is shown on the font dialog by specifying $False to some of the properties if needed. This helps to avoid any unnecessary issues along the way. Lets make a few selections on this dialog and then we can click OK.

image

I have to dig into the $fontdialog object to find the various settings that were selected; in the case the font property of the object. Also note that if you hit OK, the result returned from the dialog is OK and if you hit Cancel, the result returned will be Cancel. Makes it easier to specify the proper logic to handle each action.

image

Here you can see see the Bold property is set to True, which is what I selected as well as the Size property as 12. Diving a bit deeper into the FontFamily property is where we can identify the font family that will be used.

So you can get an idea as to what you have to do in order to see what was selected. If you are only focused on allowing a few things for the font selection regardless of what is selected, then you just grab those properties, otherwise you can grab everything that is needed. Now lets take a look at how I used this in my PoshChat client with a helper function I wrote called Invoke-FontDialog.

Function Script:Invoke-FontDialog {
    [cmdletbinding()]
    Param (
        $Control,
        [switch]$ShowColor,
        [switch]$FontMustExist,
        [switch]$HideEffects
    )
    Begin {
        $Script:fontDialog = new-object windows.forms.fontdialog
        $fontDialog.AllowScriptChange = $False
        If ($PSBoundParameters['ShowColor']) {
            $fontDialog.Showcolor = $True
            $fontDialog.Color = $colors[$Control.Foreground.Color.ToString()]
        }
        If ($PSBoundParameters['FontMustExist']) {
            $fontDialog.FontMustExist = $True
        }   
        If ($PSBoundParameters['HideEffects']) {
            $fontDialog.ShowEffects = $False
        }          
        $styles = New-Object System.Collections.Arraylist
        $textDecorations = $Control.TextDecorations | Select -Expand Location
        If ($textDecorations -contains "Underline") {
            $Styles.Add("Underline") | Out-Null
        }
        If ($textDecorations -contains "Strikethrough") {
            $Styles.Add("Strikeout") | Out-Null
        }    
        If ($Inputbox_txt.FontStyle -eq "Italic") {
            $Styles.Add("Italic") | Out-Null
        } 
        If ($Inputbox_txt.FontWeight -eq "Bold") {
            $Styles.Add("Bold") | Out-Null
        } 
        If ($styles.count -eq 0) {
            $style = "Regular"
        } Else {
            $style = $styles -join ","
        }
    }
    Process {
        $fontDialog.Font = New-Object System.Drawing.Font -ArgumentList $Control.Fontfamily.source,$Control.FontSize,$Style,"Point"
        If ($fontDialog.ShowDialog() -eq "OK") {        
            $Control.fontsize =  $FontDialog.Font.Size
            If ($PSBoundParameters['ShowColor']) {
                $Control.Foreground = $colors[$FontDialog.Color.Name]
            }
            $Control.FontFamily = $fontDialog.Font.FontFamily.Name
            If ($fontDialog.Font.Bold) {
                $Control.FontWeight = "Bold"
            } Else {
                $Control.FontWeight = "Regular"
            }
            If ($fontDialog.Font.Italic) {
                $Control.FontStyle = "Italic"
            } Else {
                $Control.FontStyle = "Normal"
            }     
            If (-Not $PSBoundParameters['HideEffects']) {
                $textDecorationCollection = new-object System.Windows.TextDecorationCollection 
                If ($fontDialog.Font.Underline) {
                    $underline = New-Object System.Windows.TextDecoration
                    $underline.Location = 'Underline'
                    $textDecorationCollection.Add($underline)
                }
                If ($fontDialog.Font.Strikeout) {
                    $strikethrough = New-Object System.Windows.TextDecoration
                    $strikethrough.Location = 'strikethrough'
                    $textDecorationCollection.Add($strikethrough)   
                }
                If ($textDecorationCollection.Count -gt 0) {
                    #Sometimes a control does not have a TextDecorations property
                    If ($Control | Get-Member -Name TextDecorations) {
                        $Control.TextDecorations = $textDecorationCollection
                    }
                }
            }
        }
    }
} 

This function will take the control object (a richtextbox for instance) and then applies specific font selections to that window so you can see results like below:

Before:

image

After:

image

Here I changed the color of the text to green, set the font family to Arial, Bold text and font size of 18. Pretty cool stuff! In the case of my client, I had 3 different windows that displayed text and had to handle those separately.  Depending on what type of control you are using, your mileage will vary on how to properly set the values given from the font dialog box to the specific control. Because all of mine are rich textboxes, I do not have to worry much about what happens in the function.

##InputBox Font event
$InputBoxFont.Add_Click({
    Invoke-FontDialog -Control $Inputbox_txt -ShowColor -FontMustExist
})
##OnlineUser Font event
$OnlineUsersFont.Add_Click({
    Invoke-FontDialog -Control $OnlineUsers -ShowColor -FontMustExist
})
##MessageWindow Font event
$MessageWindowFont.Add_Click({
    Invoke-FontDialog -Control $MainMessage -FontMustExist
})

The only difference between all of the text windows here is that the Message window is not allowing Colors to be used (this is because I handle specific types of messages with different colors). How do I handle this? Well, since –ShowColor is not being used, the ShowColor value is set to $False instead of being set to $True. This means that you get the following type of font dialog instead:

image

Now the option to select a font color is no longer available for a user to select! The font selection dialog is pretty flexible to use and gives the users an extra option in customizing their experience with a UI. 

This entry was posted in powershell and tagged , , . Bookmark the permalink.

2 Responses to Font Dialog Selection using PowerShell

  1. pamarths says:

    Hi, Thanks for sharing. This is quite useful. One thing I am not able to understand is, why you are treating this as WPF? I see that you are using Windows Forms(not any WPF related controls).

    • Boe Prox says:

      You got me there. I was a little overzealous with the title because most of my UI articles deal with WPF and it was a little later in the evening so I really wasn’t paying the best attention. I will update the title so it better reflects what is going on.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s