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()
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.
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.
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:
After:
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:
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.
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).
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.