Page 1 of 1

Intro to "skinning" an application Rate Topic: ****- 1 Votes

#1 modi123_1  Icon User is online

  • Suitor #2
  • member icon

Reputation: 8952
  • View blog
  • Posts: 33,557
  • Joined: 12-June 08

Post icon  Posted 13 May 2009 - 07:40 PM


Skinning a VB.NET application is not as difficult as it initially seems. There are subtle visual tricks you can manipulate to create the desired effects.

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) background
(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.

Genera logic:

    '-- 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
            '-- 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

    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".

Attached Image

Attached File(s)

Is This A Good Question/Topic? 7
  • +

Replies To: Intro to "skinning" an application

#2 raziel_  Icon User is offline

  • Like a lollipop
  • member icon

Reputation: 464
  • View blog
  • Posts: 4,255
  • Joined: 25-March 09

Posted 20 July 2010 - 10:19 AM

a very very nice job ty so much :)
Was This Post Helpful? 0
  • +
  • -

#3 biggerB  Icon User is offline

  • If at first you donít succeed, call it version 1.0
  • member icon

Reputation: 80
  • View blog
  • Posts: 760
  • Joined: 11-June 10

Posted 22 July 2010 - 10:44 AM

Great work on the tutorial...

+ rep..
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1