Click here to Skip to main content
15,867,488 members
Articles / Multimedia / GDI+

Windows Forms Controls: VB.NET Translucent Control using GDI+

Rate me:
Please Sign up or sign in to vote.
4.31/5 (11 votes)
10 Jun 2014CPOL4 min read 116.9K   10K   49   26
Build a standard Windows Forms translucent control using GDI+ & VB.NET

Image 1

Introduction

The main purpose of this article is to show how to build your own Transparent Control in VB.NET by extending the control through inheritance.

Also, the class might be used as a base class to build your own custom transparent controls such as PictureBox, Button, Panel, .....etc.

Background

Since the Windows Form Control is the only control that supports transparency through its Opacity property, I decided to utilize the same strategy to build a control that supports transparency.

I saw so many articles talks about the transparency of the control, and I had studied most of the techniques which discuss the same issue and some of these techniques are listed below:

  • To call InvokePaintBackground of the control’s parent and override the OnPaintBackground event.
  • To draw image which supports transparency to avoid the issues due to double buffering and flickering?
  • To override CreateParams property, set ExStyle value to support transparency and on OnPaintBackground event, fill the control’s ClientRectangle with a transparent color.

Control's Behavior

According to MSDN, the control class owns three methods which allow setting or checking the behavior of the control:

  1. SetStyle method: Used to set the ControlStyles bit to a specified value either to True or False
  2. GetStyle method: Used to retrieve the ControlStyles bit
  3. UpdateStyles method: Used to force the assigned ControlStyles bit to be reapplied to the control, as this method will call CreateParams method to get the ControlStyles bits to apply to ExStyle and Style
  4. ControlStyles Enum: Used with SetStyle method to specify the style and the behavior of the control

Since UpdateStyles method allows us to change the styles in CreateParams method, I believe we shall not override the CreateParams method at all. But sometimes, we may need to do that based on code requirements.

For further details about SetStyle, ControlStyles Enum, GetStyle and UpdateStyles, you may check MSDN.

Using the Code

The concepts behind the transparent control are categorized as follows:

  • Use the SetStyle and UpdateStyles methods to change the styles in CreateParams method, which can be done in Control Constructor:
    VB.NET
        #Region " Constructor "
         Public Sub New()
    
            SetStyle(ControlStyles.SupportsTransparentBackColor, True)
            SetStyle(ControlStyles.Opaque, False)
            SetStyle(ControlStyles.DoubleBuffer, True)
            SetStyle(ControlStyles.AllPaintingInWmPaint, True)
            SetStyle(ControlStyles.UserPaint, True)
            UpdateStyles()
            ' ......... rest of the code 
            
        End Sub
    
    #End Region
  • BackColor property: Overrides the control’s BackColor property, sets its value to Color.Transparent and uses attributes to hide the property.
    VB.NET
    <System.ComponentModel.Browsable(False)> _
    <System.ComponentModel.EditorBrowsable_
    (System.ComponentModel.EditorBrowsableState.Never)> _
    <System.ComponentModel.DefaultValue(GetType(Color), "Transparent")> _
    <System.ComponentModel.Description("Set background color.")> _
    <System.ComponentModel.Category("Control Style")> _
    Public Overrides Property BackColor() As System.Drawing.Color
        Get
            Return m_backcolor
        End Get
        Set(ByVal value As System.Drawing.Color)
            m_backcolor = value
            Refresh()
        End Set
    End Property
    
  • Opacity property: This property will be used to set the opacity percentage of the control and we shall use UpdateStyles method within this property to set the control behavior as explained before. Also, I was about to write a class to convert the opacity value to and from a string, but in .NET, there is a built in OpacityConverter class, just saved some time.
    VB.NET
    <System.ComponentModel.Browsable(True)> _
    <System.ComponentModel.EditorBrowsable_
    (System.ComponentModel.EditorBrowsableState.Always)> _
    <System.ComponentModel.DefaultValue(1.0R)> _
    <System.ComponentModel.TypeConverter(GetType(OpacityConverter))> _
    <System.ComponentModel.Description_
    ("Set the opacity percentage of the control.")> _
    <System.ComponentModel.Category("Control Style")> _
    Public Overridable Property Opacity() As Double
        Get
            Return m_opacity
        End Get
        Set(ByVal value As Double)
            If value = m_opacity Then
                Return
            End If
            m_opacity = value
            UpdateStyles()
            Refresh()
        End Set
    End Property
    
  • Transparent property: Indicates if the control should be transparent or not. When the value is set to false, the transparency of the control will be skipped, and the control behaves as normal.
    VB.NET
    <System.ComponentModel.Browsable(True)> _
    <System.ComponentModel.EditorBrowsable_
    (System.ComponentModel.EditorBrowsableState.Always)> _
    <System.ComponentModel.DefaultValue(GetType(Boolean), "False")> _
    <System.ComponentModel.Description("Enable control trnasparency.")> _
    <System.ComponentModel.Category("Control Style")> _
    Public Overridable Property Transparent() As Boolean
        Get
            Return m_transparent
        End Get
        Set(ByVal value As Boolean)
            If value = m_transparent Then
                Return
            End If
            m_transparent = value
            Refresh()
        End Set
    End Property
    
  • TransparentColor property: This property will be used to set the fill color which will be used to fill and draw the Control’s ClientRectangle:
    VB.NET
    <System.ComponentModel.Browsable(True)> _
     <System.ComponentModel.EditorBrowsable_
     (System.ComponentModel.EditorBrowsableState.Always)> _
     <System.ComponentModel.DefaultValue(GetType(Color), "DodgerBlue")> _
     <System.ComponentModel.Description("Set the fill color of the control.")> _
     <System.ComponentModel.Category("Control Style")> _
     Public Overridable Property TransparentColor() As Color
         Get
             Return m_transparentColor
         End Get
         Set(ByVal value As Color)
             m_transparentColor = value
             Refresh()
         End Set
     End Property
    

Draw the Control's Transparency

The trick behind transparency is to paint the control's ClientRectangle with a SolidBrush where its value will be set using BackColor property:

VB.NET
Using sb As New SolidBrush(control.BackColor)
            g.FillRectangle(sb, control.ClientRectangle)
            sb.Dispose()

            ' .....rest of the code

Then we shall fill the control’s clientRectangle with another SolidBrush where its value will be set by using TransparentColor property and Opacity property:

VB.NET
Using sbt As New SolidBrush(Color.FromArgb_
    (control.Opacity * 255, control.TransparentColor))
    g.FillRectangle(sbt, control.ClientRectangle)
    sbt.Dispose()
End Using
' ......rest of the code 

Draw the Control’s Background method:

VB.NET
Public Overridable Sub DrawBackground_
(ByVal g As Graphics, ByVal control As TransparentControl)

    If Transparent Then

        Using sb As New SolidBrush(control.BackColor)
            g.FillRectangle(sb, control.ClientRectangle)
            sb.Dispose()

            Using sbt As New SolidBrush(Color.FromArgb_
    (control.Opacity * 255, control.TransparentColor))
                g.FillRectangle(sbt, control.ClientRectangle)
                sbt.Dispose()
            End Using
        End Using

    Else

        Using sb As New SolidBrush(control.TransparentColor)
            g.FillRectangle(sb, control.ClientRectangle)
            sb.Dispose()
        End Using
    End If

End Sub

We can draw whatever we want based on our requirements and pass the code to the OnPaint event, for example let us add borders to the control and for that, there are two additional functions which will be used to make the value of TransparentColor property darker or lighter, those two functions are also connected with the opacity property:

VB.NET
Private Function GetLightColor(ByVal colorIn As Color, _
        ByVal percent As Single) As Color
    If percent < 0 OrElse percent > 100 Then
        Throw New ArgumentOutOfRangeException("percent must be between 0 and 100")
    End If
    Dim a As Int32 = colorIn.A * Me.Opacity
    Dim r As Int32 = colorIn.R + CInt(((255 - colorIn.R) / 100) * percent)
    Dim g As Int32 = colorIn.G + CInt(((255 - colorIn.G) / 100) * percent)
    Dim b As Int32 = colorIn.B + CInt(((255 - colorIn.B) / 100) * percent)
    Return Color.FromArgb(a, r, g, b)
End Function

Private Function GetDarkColor(ByVal colorIn As Color, _
        ByVal percent As Single) As Color
    If percent < 0 OrElse percent > 100 Then
        Throw New ArgumentOutOfRangeException("percent must be between 0 and 100")
    End If
    Dim a As Int32 = colorIn.A * Me.Opacity
    Dim r As Int32 = colorIn.R - CInt((colorIn.R / 100) * percent)
    Dim g As Int32 = colorIn.G - CInt((colorIn.G / 100) * percent)
    Dim b As Int32 = colorIn.B - CInt((colorIn.B / 100) * percent)
    Return Color.FromArgb(a, r, g, b)
End Function

Draw the Control’s Border method:

VB.NET
Public Overridable Sub DrawBorder(ByVal g As Graphics, _
        ByVal control As TransparentControl)
    Using p As New Pen(GetDarkColor(Me.TransparentColor, 40), 1)
        Dim rect As New Rectangle(ClientRectangle.X, ClientRectangle.Y, _
    ClientRectangle.Width - 1, ClientRectangle.Height - 1)
        rect.Inflate(-1, -1)
        g.DrawRectangle(p, rect)
        p.Dispose()
    End Using

Now let us pass both DrawBackground and DrawBorder methods to the Control’s OnPaint event to finish the work:

VB.NET
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
    MyBase.OnPaint(e)

    DrawBackground(e.Graphics, Me)
    DrawBorder(e.Graphics, Me)

End Sub

I believe we can use the same technique to draw anything inside the control and the same shall supports opacity. Also we can use the same strategy to build some other translucent controls.

The control also supports smart tags technology. For further details about how to add smart tags to the control, you may check MSDN.

Finally, just build the control and use it in your form.

Note

The source code was written with Visual Studio 2008, .NET Framework 3.5.

History

  • 10th October, 2009: First release
  • 13th October, 2009: Version 1.1

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Engineer
Egypt Egypt
Oil & Gas Engineer
C# & VB.net
Coding For Fun Only

Comments and Discussions

 
QuestionTransparency not showing on picturebox Pin
raslasagar21-Jan-16 11:15
raslasagar21-Jan-16 11:15 
QuestionGood Post. Pin
Bhavesh Patel27-Jul-15 18:43
Bhavesh Patel27-Jul-15 18:43 
QuestionPainting/Plotting to control Pin
Member 1069925325-Mar-14 15:58
Member 1069925325-Mar-14 15:58 
AnswerRe: Painting/Plotting to control Pin
Member 1069925325-Mar-14 18:29
Member 1069925325-Mar-14 18:29 
QuestionAfter downloading the file cannot be opened Pin
Member 99726328-Apr-13 3:15
professionalMember 99726328-Apr-13 3:15 
QuestionTransparent for picture box Pin
susindran27-Dec-12 0:32
susindran27-Dec-12 0:32 
AnswerRe: Transparent for picture box Pin
Casey Sheridan26-Mar-13 15:11
professionalCasey Sheridan26-Mar-13 15:11 
Questionvb.net 2005 Pin
Res2Hack23-Aug-12 21:39
Res2Hack23-Aug-12 21:39 
AnswerRe: vb.net 2005 Pin
a_pess2-Oct-12 17:24
a_pess2-Oct-12 17:24 
Questiondownloads Pin
dvankeuren18-Jul-12 9:07
dvankeuren18-Jul-12 9:07 
GeneralHerramienta Perfecta Pin
elroger108-Jul-12 9:07
elroger108-Jul-12 9:07 
GeneralMy vote of 5 Pin
Manoj Kumar Choubey23-Feb-12 21:46
professionalManoj Kumar Choubey23-Feb-12 21:46 
GeneralTransparent Image Pin
dim1319-Dec-10 6:49
dim1319-Dec-10 6:49 
Generalcustomer control! Pin
firetix10-Apr-10 9:51
firetix10-Apr-10 9:51 
QuestionExtending your controls Pin
donaldn200615-Nov-09 12:12
donaldn200615-Nov-09 12:12 
AnswerRe: Extending your controls Pin
a_pess13-Dec-09 12:23
a_pess13-Dec-09 12:23 
GeneralSome issues extending the translucent control Pin
Sean_Miller9-Nov-09 2:46
Sean_Miller9-Nov-09 2:46 
GeneralRe: Some issues extending the translucent control Pin
a_pess13-Dec-09 12:21
a_pess13-Dec-09 12:21 
will, i had build a Picture Box control support transparency, you may contact me through email (silverlight1212@yahoo.com) i will be glad to send it to you
GeneralFunctionality Pin
Klaus Luedenscheidt20-Oct-09 22:57
Klaus Luedenscheidt20-Oct-09 22:57 
GeneralRe: Functionality Pin
a_pess21-Oct-09 1:48
a_pess21-Oct-09 1:48 
GeneralRe: Functionality Pin
Klaus Luedenscheidt21-Oct-09 19:32
Klaus Luedenscheidt21-Oct-09 19:32 
GeneralRe: Functionality Pin
a_pess21-Oct-09 23:42
a_pess21-Oct-09 23:42 
GeneralRe: Functionality Pin
Klaus Luedenscheidt22-Oct-09 1:47
Klaus Luedenscheidt22-Oct-09 1:47 
GeneralUsing () Pin
Andy Davies19-Oct-09 5:16
Andy Davies19-Oct-09 5:16 
GeneralRe: Using () Pin
Jon_Boy19-Oct-09 5:22
Jon_Boy19-Oct-09 5:22 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.