Visual Basic.Net Pullout Panel Borderless Form
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 effect.
http://www.freeimagehosting.net/newuploads/w4inl.png
Steps:
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
MyBase.OnPaint(e)
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
Me.BringToFront()
'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
MyBase.OnMouseDown(e)
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
MyBase.OnMouseUp(e)
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
Me.Invalidate()
End If
Else
'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
'redraw
Me.Invalidate()
Else
'otherwise the proposed width
'will be used
Me.Width = ProposedWidth
'redraw
Me.Invalidate()
End If
End If
End If
MyBase.OnMouseMove(e)
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
Else
'Add a sizechanged event handler
AddHandler DirectCast(ParentObject, Control).SizeChanged, AddressOf ParentSizeChanged
End If
End If
MyBase.OnParentChanged(e)
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
'redraw
Parent.Invalidate(True)
End If
Else
If Me.Width > DirectCast(sender, Control).ClientRectangle.Width Then
Me.Width = DirectCast(sender, Control).ClientRectangle.Width - Me.Left
'redraw
Parent.Invalidate(True)
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)
SliderPanel1.Invalidate()
'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
References
- MSDN Library http://msdn.microsoft.com/en-us/
- MSDN Forums http://social.msdn.microsoft.com/Forums/en-US/categories