How To Create a Borderless form with pull out compartments in Visual Basic.

This can be difficult at first, but i will attempt to keep it short and sweet.

Have you ever wanted to have a compartment that you could pull out of your form, one that extended beyond the border of the form? Well, this example doesn't exactly do that, but it does something that provides the same visual affect.


This section should include a description of the outcome; i.e., what will happen if the steps are followed (a task is completed, an application is installed, or the internet becomes available).

  • 1.) Create a new Visual Basic windows forms project.
  • 2.) Add a new Class file to the project and replace all of that file's code with the following class(note the code is commented). 
Option Strict On
Public Class SliderPanel
    'Inherits means that this object will "inherit", or otherwise have the
    'same properties as what it is inheriting from(panel in this case).
    Inherits Panel
    'This property is for setting the height of the notch handle of the pullout
    Public Property HandleHeight As Integer = 10
    'This property is for setting how wide the notch handle portion of the pullout will be
    Public Property HandleWidth As Integer = 10
    'This is a switch for determining when the user is pulling the panel out.
    Dim UpdatingSize As Boolean
    'This variable stores the parent of this control for access in later routines
    Dim ParentObject As Object
    Sub New()
        'This panel does a lot of painting, so we make sure its doublebuffered.
        Me.DoubleBuffered = True
        'We set the cursor to hand
        Me.Cursor = Cursors.Hand
        'We make sure the backcolor of this panel is transparent
        Me.BackColor = Color.Transparent
    End Sub
    'We use overrides OnPaint so we can access the graphics object before event delegates are created
    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
        'Capture the graphics object into a variable
        Dim Graphics As Graphics = e.Graphics
        'Calculate a factor for calculating the locations of the corners of the notches
        Dim Offset As Integer = CInt((Me.Height - HandleHeight) / 2)
        'Create a rectangle to fill the greater part of the notch handle
        Dim R1 As New Rectangle(New Point(0, CInt((Me.Height / 2) - (HandleHeight / 2))), New Size(Me.Width, HandleHeight))
        'this will be the color of the tab that pulls out
        Dim FillBaseColor As Color = Color.Tan
        'this will be the translucency of the tab control
        Dim FillAlpha As Integer = 255
        'Create a fill brush, combining the fillalpha and the base color
        Dim FillBrush As New SolidBrush(Color.FromArgb(FillAlpha, FillBaseColor.R, FillBaseColor.G, FillBaseColor.B))
        'Calculate 3 points to fill the upper triangle
        Dim P1 As New Point(Me.Width - HandleWidth, 0)
        Dim P2 As New Point(Me.Width, Offset)
        Dim P3 As New Point(Me.Width - HandleWidth, Offset)
        'Calculate 3 points to fill the lower triangle
        Dim B1 As New Point(Me.Width - HandleWidth, Me.Height)
        Dim B2 As New Point(Me.Width - HandleWidth, Me.Height - Offset)
        Dim B3 As New Point(Me.Width, Me.Height - Offset)
        'Calculate the rectangle for filling the greater portion of the pullout(discluding the handle)
        Dim R2 As New Rectangle(0, 0, Me.Width - HandleWidth, Me.Height)
        'Calculate the last rectangle which goes into the notch(in the center of the two triangles)
        Dim R3 As New Rectangle(Me.Width - HandleWidth, Offset, HandleWidth, Me.Height - (Offset * 2))
        'Draw the upper triangle(you can comment out any of these to see what it's doing)
        Graphics.FillPolygon(FillBrush, {P1, P2, P3})
        'Draw the lower triangle
        Graphics.FillPolygon(FillBrush, {B1, B2, B3})
        'Draw the main area of the pullout
        Graphics.FillRectangle(FillBrush, R2)
        'Draw the rectangle inbetween the upper triangle and the lower triangle
        Graphics.FillRectangle(FillBrush, R3)
        'Outline our pullout with black lines
        Graphics.DrawLine(Pens.Black, P1, P2)
        Graphics.DrawLine(Pens.Black, B1, B3)
        Graphics.DrawLine(Pens.Black, New Point(P2.X - 1, P2.Y), New Point(B3.X - 1, B3.Y))
        Graphics.DrawLine(Pens.Black, New Point(0, 0), P1)
        Graphics.DrawLine(Pens.Black, New Point(0, Me.Height - 1), New Point(B1.X, B1.Y - 1))
        Graphics.DrawLine(Pens.Black, New Point(0, 0), New Point(0, Me.Height - 1))
        'create the delegates for the paint event
    End Sub
    Protected Overrides Sub OnMouseDown(ByVal e As System.Windows.Forms.MouseEventArgs)
        'This is still somewhat of a test....
        'This places the current panel that has been clicked
        'on top of other panels if they overlap
        'the mouse is down, so now we get ready to pull out the tab<goto the mousemove event>
        'we make a mental note that we're updating now
        UpdatingSize = True
    End Sub
    Protected Overrides Sub OnMouseUp(ByVal e As System.Windows.Forms.MouseEventArgs)
        'Mouse is no longer down, so we are no longer updating
        UpdatingSize = False
    End Sub
    Protected Overrides Sub OnMouseMove(ByVal e As System.Windows.Forms.MouseEventArgs)
        'If the mouse is still down, then this value is still true
        If UpdatingSize Then
            'Check if the mouse's X location is smaller than
            'the panel's handle width
            If e.Location.X < Me.HandleWidth Then
                'If the mouse's X location is then
                'Check that you are not expanding the
                'panel beyond the invisible window(we're still really in the bounds of a form)
                If e.Location.X < Parent.ClientRectangle.Width - Me.Left Then
                    'set the width of this panel
                    Me.Width = Me.HandleWidth
                    'invalid call paint event
                End If
                'Check if updating the
                'width will cause the panel to
                'extend beyond the bounds of the invisible form
                Dim ProposedWidth As Integer = e.Location.X
                If Me.Left + ProposedWidth > Parent.ClientRectangle.Width Then
                    'if it will, set it to be as wide is it can be
                    'while remaining visible
                    Me.Width = Parent.ClientRectangle.Width - Me.Left
                    'otherwise the proposed width
                    'will be used
                    Me.Width = ProposedWidth
                End If
            End If
        End If
    End Sub
    Protected Overrides Sub OnParentChanged(ByVal e As System.EventArgs)
        'Change the stored parent object
        ParentObject = Me.Parent
        If Not ParentObject Is Nothing Then
            'Check if the parent object is a form or a control
            If TypeOf (ParentObject) Is Form Then
                'Add a sizechanged event handler
                AddHandler DirectCast(ParentObject, Form).SizeChanged, AddressOf ParentSizeChanged
                'Add a sizechanged event handler
                AddHandler DirectCast(ParentObject, Control).SizeChanged, AddressOf ParentSizeChanged
            End If
        End If
    End Sub
    Private Sub ParentSizeChanged(ByVal sender As Object, ByVal e As EventArgs)
        'Check if the parent object is a form or a control
        If TypeOf (sender) Is Form Then
            'Set the width of this to be the distance inbetween
            'this panel's left and the parent's client rectangle.width
            If Me.Width > DirectCast(sender, Form).ClientRectangle.Width Then
                Me.Width = DirectCast(sender, Form).ClientRectangle.Width - Me.Left
            End If
            If Me.Width > DirectCast(sender, Control).ClientRectangle.Width Then
                Me.Width = DirectCast(sender, Control).ClientRectangle.Width - Me.Left
            End If
        End If
    End Sub
End Class

  • 3.) Replace Form1's code with the following code:
'Option strict is good for preventing the coding of errors
Option Strict On
Public Class Form1
    'Create a new instance of the sliderpanel
    Friend WithEvents SliderPanel1 As New SliderPanel With {.Parent = Me, .Height = 200}
    'Create a regular panel(this will be our borderless form)->with some properties
    Friend WithEvents Panel1 As New Panel With {.Location = New Point(331, 154), .Size = New Size(551, 424), .Parent = Me, .BackColor = Color.Silver, .BorderStyle = BorderStyle.FixedSingle}
    'Variable for moving the form
    Dim Dragging As Boolean
    'variable for moving the form
    Dim MouseLocation As New Point
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'Make the form's back color and transparency key the same
        Me.BackColor = Color.Thistle
        Me.TransparencyKey = Me.BackColor
        'make the form nice and big
        Me.Size = New Size(1237, 833)
        'make the form borderless
        Me.FormBorderStyle = Windows.Forms.FormBorderStyle.None
        'make the form doublebuffered for paint events
        Me.DoubleBuffered = True
        'this number will be how much shorter the pullout tab will be than the panel
        Dim SizeDifference As Integer = 50
        'set the slider's width to the handle width(for startup)--->closed
        SliderPanel1.Width = SliderPanel1.HandleWidth
        'Set the height of the panel(slider)
        SliderPanel1.Height = Panel1.Height - SizeDifference
        'Set the height of the edge of the handle to 95% of the height of the panel(slider)
        SliderPanel1.HandleHeight = CInt(SliderPanel1.Height * 0.95)
        'Set the location of the panel(slider)
        SliderPanel1.Top = Panel1.Top + (SizeDifference \ 2)
        SliderPanel1.Left = Panel1.Left + Panel1.Width - 1
        'update the panel (slider)
        'Add the handlers to the panel for dragging the form around on the screen
        AddHandler Panel1.MouseDown, AddressOf Panel1_MouseDown
        AddHandler Panel1.MouseMove, AddressOf Panel1_MouseMove
        AddHandler Panel1.MouseUp, AddressOf Panel1_MouseUp
    End Sub
    Private Sub Panel1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
        'enable moving of the form
        Dragging = True
        'Store mouse location
        MouseLocation.X = Windows.Forms.Cursor.Position.X - Me.Left
        MouseLocation.Y = Windows.Forms.Cursor.Position.Y - Me.Top
    End Sub
    Private Sub Panel1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
        'Check if moving the form is enabled
        If Dragging Then
            'if it is, set the new location of the form(this will keep happening while the mouse is down and moving)
            Me.Top = Windows.Forms.Cursor.Position.Y - MouseLocation.Y
            Me.Left = Windows.Forms.Cursor.Position.X - MouseLocation.X
        End If
    End Sub
    Private Sub Panel1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
        'disable moving of the form
        Dragging = False
    End Sub
End Class


I hope you find this helpful!