This tutorial will cover changing a form's background to something spiffy, and change a button as well.
This tutorial will not cover advanced topics like:
- generating a list of skins and choosing one
- altering location of button information from an XML file
- "reskinning" other toolbox controls (group boxes, text boxes, labels, etc).
The last item is not too monumental - take what you read here regarding the button and you can make it happen.
"Skinning" or "reskinning" is a term loosely used to indicate changing the appearance and layout of the present graphical user interface (GUI).
A "skin" is the total package of images you want to have replace the current style.
A good example of this is the Winamp player. You have the default look, but can install (or make) new skins that override the default to pretty nifty effect.
Unfortunately there is no simply way to add this to a program outside of directly adding the code. Sorry - this cannot be too object-ified. There are specific button events that need to be declared and used.
Global view of what is happening:
The form is a fairly static control. You have the background image or you do not. Changing this is a straight forward assignment of a new image, setting a few properties to make sure it fits, and you are done.
A button is more tricky. If you look at the default button from the tool box there are a few things going on in the background Microsoft does for you. There are three "states" a button goes through when the appearance changes.
First when you click (and hold) on a button the appearance changes. This image change is triggered by the "mouse down" event. This can be considered an image.
Second you have the default button appearance. This is how the button loads up, but also when a "mouse up" event occurs the down image mentioned above reverts back to the default image. This can be considered as one image.
Third there is the 'mouse over' event. When you move your cursor (no clicking) over a button it changes to indicate you are in a hotzone and can click it. This is controlled by the 'mouse enter' event. When the cursor enters the border of a button the image changes.
With this when the cursor leaves the border of a button the image reverts back to the 'mouse up' image.
As of right now that's four images:
(1) button: mouse up
(1) button: mouse down
(1) button: mouse over
You will need to create the images using what ever program you so desire. I would highly suggest making them PNG format and the image on a transparent background. This will allow you to make rounded corners and shaded effects.
'-- 1.0 a boolean to determine which style we are in '-- normal = true, skinned = false Private _bStyleNormal As Boolean = True '-- there are three states to a button: mouse up, mouse down, and mouse over. '-- since there are three states we need to have three separate images for one button. '-- this will hold true for any control. '-- 4.0 the stylized button up Private _buttonUp As Bitmap = Nothing '-- 5.0 the stylized button down Private _buttonDown As Bitmap = Nothing '-- 6.0 the stylized mouse over Private _buttonOver As Bitmap = Nothing
When we thought the states we essentially broke down the logic.
When we are wanting the skinned button effects we have to take care of the specific image for the button in that state.
''' <summary> ''' If the mouse is down on the button (button being clicked) switch the background image ''' </summary> ''' <param name="sender"></param> ''' <param name="e"></param> ''' <remarks></remarks> Private Sub uxButtonSwitch_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles uxButtonSwitch.MouseDown If Not _bStyleNormal Then Me.uxButtonSwitch.BackgroundImage = _buttonDown End Sub ''' <summary> ''' Part one of the 'mouse over'. If the cursor is in the mouse limits set the background to the mouse over image. ''' </summary> ''' <param name="sender"></param> ''' <param name="e"></param> ''' <remarks></remarks> Private Sub uxButtonSwitch_MouseEnter(ByVal sender As Object, ByVal e As System.EventArgs) Handles uxButtonSwitch.MouseEnter If Not _bStyleNormal Then Me.uxButtonSwitch.BackgroundImage = _buttonOver End Sub ''' <summary> ''' Part two of the 'mouse over' state.. once the cursor leaves the mouse boundaries set the image to mouse up image. ''' </summary> ''' <param name="sender"></param> ''' <param name="e"></param> ''' <remarks></remarks> Private Sub uxButtonSwitch_MouseLeave(ByVal sender As Object, ByVal e As System.EventArgs) Handles uxButtonSwitch.MouseLeave If Not _bStyleNormal Then Me.uxButtonSwitch.BackgroundImage = _buttonUp End Sub ''' <summary> ''' If the mouse is up on the button (after button being clicked) switch the background image ''' </summary> ''' <param name="sender"></param> ''' <param name="e"></param> ''' <remarks></remarks> Private Sub uxButtonSwitch_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles uxButtonSwitch.MouseUp If Not _bStyleNormal Then Me.uxButtonSwitch.BackgroundImage = _buttonUp End Sub
That's not too bad, right? Each time one of the states we are looking for (mouse click down, mouse click up, entering/exiting the button) we change the background to the appropriate image. Simply put we are just swapping the background image of the button at specific times!
Now let's get the meat of the style change.
With changing the background of the form we have to only worry about:
- the image
- if the image is stretched, tiled, etc
- and the border
The button is a bit more complex:
- the image
- if the image is stretched, tiled, etc
- the button appearance (needs to be flat so no default microsoft settings show up)
- the button's border (don't want to that to show - it would disrupt the design you made!)
- the mouse over and mouse down background coloring. We want our own to show up so we set everything to transparent to hide it.
- the images I created for the button are a bit big so I will make the button size a bit bigger.
- the button's font...
''' <summary> ''' The "guts" of the reskinning. Change the properties of the form's background and a button to our new cool style. ''' Also allows you to change it back ''' </summary> ''' <remarks></remarks> Private Sub LoadSkin() '-- Two parts - the normal style and the new skin. If _bStyleNormal Then '-- 1.0 If the style should be 'normal' set the following properties. '-- 1.1 The images on the form background and the button go back to nothing Me.BackgroundImage = Nothing Me.uxButtonSwitch.BackgroundImage = Nothing '-- 1.2 Set the the image layouts back to tile for hte form and the button Me.BackgroundImageLayout = ImageLayout.Tile Me.uxButtonSwitch.BackgroundImageLayout = ImageLayout.Tile '-- 1.3 Reset the buton style to the system default Me.uxButtonSwitch.FlatStyle = FlatStyle.System '-- 1.4 Reset the buton border to 1 Me.uxButtonSwitch.FlatAppearance.BorderSize = 1 '-- 1.5 The button colors go back to color "control". Me.uxButtonSwitch.BackColor = Drawing.SystemColors.Control Me.uxButtonSwitch.FlatAppearance.MouseOverBackColor = Drawing.SystemColors.Control Me.uxButtonSwitch.FlatAppearance.MouseDownBackColor = Drawing.SystemColors.Control '-- 1.6 We changed the button height - reset that Me.uxButtonSwitch.Height = 23 '-- 1.7 Remove the button's bold font Me.uxButtonSwitch.Font = New Font(Me.uxButtonSwitch.Font, FontStyle.Regular) '-- 1.8 give back the form's border Me.FormBorderStyle = Windows.Forms.FormBorderStyle.Sizable Else '-- 2.0 The style is going to be our fancy style... '-- 2.1 Set the form's height and width to our background image's height and width Me.Height = 200 Me.Width = 400 '-- 2.2 The images on the form background and the button go our loaded fancy images Me.BackgroundImage = _background Me.uxButtonSwitch.BackgroundImage = _buttonUp '-- 2.3 Stretch our fancy images to fit the controls right. Me.BackgroundImageLayout = ImageLayout.Stretch Me.uxButtonSwitch.BackgroundImageLayout = ImageLayout.Stretch '-- 2.4 Make the buton flat. This gets ride of the nice default gradient Me.uxButtonSwitch.FlatStyle = FlatStyle.Flat '-- 2.5 The border is visible - let's hide that Me.uxButtonSwitch.FlatAppearance.BorderSize = 0 '-- 2.6 The default button has different colors for the button on mouse overs, clicks, and so forth. Hide them by making them transparent. Me.uxButtonSwitch.BackColor = Color.Transparent Me.uxButtonSwitch.FlatAppearance.MouseOverBackColor = Color.Transparent Me.uxButtonSwitch.FlatAppearance.MouseDownBackColor = Color.Transparent '-- 2.7 Change the button height just a bit so the text lines up with our images Me.uxButtonSwitch.Height = 32 '-- 2.8 Keep the same font information but make it bold Me.uxButtonSwitch.Font = New Font(Me.uxButtonSwitch.Font, FontStyle.Bold) '-- 2.9 Turn off the form's border and header... makes it look snappy Me.FormBorderStyle = Windows.Forms.FormBorderStyle.None End If '-- 3.0 Refresh the form to make sure the images get painted Refresh() End Sub
That's pretty much it. Above shows switching to the to the new skin and back again.
The attached solution
I will attach the solution (with images). It will have one button that changes, one that doesn't (this is the one that flips the style), and one form.
To make sure this works keep the image folder and the general structure alone. The form specifically looks for an 'images' folder based off it's execution in the debug folder.
Yeah.. that's a bit brittle, but for the sake of the tutorial it's needed.
When I get some time I will advance on this tutorial and make it more robust with a few different types of controls "reskinned".
Number of downloads: 2977