Skip to content

Instantly share code, notes, and snippets.

@ahmedosama007
Last active May 11, 2023 12:04
Show Gist options
  • Save ahmedosama007/39f8b76e65300e5969110b753fe0a654 to your computer and use it in GitHub Desktop.
Save ahmedosama007/39f8b76e65300e5969110b753fe0a654 to your computer and use it in GitHub Desktop.
Windows Forms Panel control with custom ScrollBars based on the Flat ScrollBar control https://gist.github.com/ahmedosama007/c1b0cd327d395a5698c1e17e96d0f8f9
'Copyright (c) Smart PC Utilities, Ltd.
'All rights reserved.
#Region "References"
Imports System.ComponentModel
#End Region
Namespace Controls
<ToolboxBitmap(GetType(Panel))> Public Class FlatPanel
Inherits Panel
Implements ITheme
#Region "Private Members"
Private _theme As UITheme = UITheme.VS2019LightBlue
Private _vScrollBar As FlatScrollBar = Nothing
Private _hScrollBar As FlatScrollBar = Nothing
#End Region
#Region "Constructor"
Public Sub New()
BorderStyle = BorderStyle.None
End Sub
#End Region
#Region "Public Properties"
<Category("Appearance")> <Description("The theme to apply to the Flat Panel control.")> <DefaultValue(GetType(UITheme), "1")> Public Overridable Property Theme As UITheme Implements ITheme.Theme
Get
Return _theme
End Get
Set(value As UITheme)
_theme = value
If _vScrollBar IsNot Nothing Then
_vScrollBar.Theme = If(_theme <> UITheme.Custom, _theme, UITheme.VS2019LightBlue)
End If
If _hScrollBar IsNot Nothing Then
_hScrollBar.Theme = If(_theme <> UITheme.Custom, _theme, UITheme.VS2019LightBlue)
End If
Invalidate(True)
End Set
End Property
<Category("Appearance")> <Description("True to allow the control to inherit the parent control style.")> <DefaultValue(True)> Public Property ParentTheme As Boolean = True Implements ITheme.ParentTheme
#End Region
#Region "Overridden Methods"
Protected Overrides Sub WndProc(ByRef m As Message)
If m.Msg = WindowMessage.WM_NCCALCSIZE AndAlso Not DesignMode Then 'Toggle ScrollBars On/Off
If _vScrollBar IsNot Nothing Then
_vScrollBar.Visible = VerticalScroll.Visible
End If
If _hScrollBar IsNot Nothing Then
_hScrollBar.Visible = HorizontalScroll.Visible
End If
ElseIf m.Msg = WindowMessage.WM_PAINT Then 'Update ScrollBars properties
If _vScrollBar IsNot Nothing AndAlso _vScrollBar.Visible Then
_vScrollBar.Minimum = VerticalScroll.Minimum
_vScrollBar.Maximum = VerticalScroll.Maximum
_vScrollBar.LargeChange = VerticalScroll.LargeChange
_vScrollBar.SmallChange = VerticalScroll.SmallChange
RemoveHandler _vScrollBar.Scroll, AddressOf VerticalScrollBar_Scroll
_vScrollBar.Value = VerticalScroll.Value
AddHandler _vScrollBar.Scroll, AddressOf VerticalScrollBar_Scroll
AdjustVScrollBarSize()
AdjustVScrollBarLocation()
End If
If _hScrollBar IsNot Nothing AndAlso _hScrollBar.Visible Then
_hScrollBar.Minimum = HorizontalScroll.Minimum
_hScrollBar.Maximum = HorizontalScroll.Maximum
_hScrollBar.LargeChange = HorizontalScroll.LargeChange
_hScrollBar.SmallChange = HorizontalScroll.SmallChange
RemoveHandler _hScrollBar.Scroll, AddressOf HorizontalScrollBar_Scroll
_hScrollBar.Value = HorizontalScroll.Value
AddHandler _hScrollBar.Scroll, AddressOf HorizontalScrollBar_Scroll
AdjustHScrollBarSize()
AdjustHScrollBarLocation()
End If
End If
MyBase.WndProc(m)
End Sub
Protected Overrides Sub OnHandleCreated(e As EventArgs)
MyBase.OnHandleCreated(e)
If _vScrollBar Is Nothing Then
_vScrollBar = New FlatScrollBar With {.Orientation = ScrollBarOrientation.Vertical, .Theme = If(_theme <> UITheme.Custom, _theme, UITheme.VS2019LightBlue)}
Parent.Controls.Add(_vScrollBar)
_vScrollBar.BringToFront()
_vScrollBar.Visible = False
AddHandler _vScrollBar.Scroll, AddressOf VerticalScrollBar_Scroll
AdjustVScrollBarSize()
AdjustVScrollBarLocation()
End If
If _hScrollBar Is Nothing Then
_hScrollBar = New FlatScrollBar With {.Orientation = ScrollBarOrientation.Horizontal, .Theme = If(_theme <> UITheme.Custom, _theme, UITheme.VS2019LightBlue), .Height = SystemInformation.HorizontalScrollBarHeight}
Parent.Controls.Add(_hScrollBar)
_hScrollBar.BringToFront()
_hScrollBar.Visible = False
AddHandler _hScrollBar.Scroll, AddressOf HorizontalScrollBar_Scroll
AdjustHScrollBarSize()
AdjustHScrollBarLocation()
End If
End Sub
Protected Overrides Sub OnSizeChanged(e As EventArgs)
MyBase.OnSizeChanged(e)
AdjustVScrollBarSize()
AdjustVScrollBarLocation()
AdjustHScrollBarSize()
AdjustHScrollBarLocation()
End Sub
Protected Overrides Sub OnMouseWheel(e As MouseEventArgs)
MyBase.OnMouseWheel(e)
If _vScrollBar IsNot Nothing AndAlso _vScrollBar.Visible Then
RemoveHandler _vScrollBar.Scroll, AddressOf VerticalScrollBar_Scroll
_vScrollBar.Value = Math.Abs(AutoScrollPosition.Y)
AddHandler _vScrollBar.Scroll, AddressOf VerticalScrollBar_Scroll
End If
If _hScrollBar IsNot Nothing AndAlso _hScrollBar.Visible Then
RemoveHandler _hScrollBar.Scroll, AddressOf HorizontalScrollBar_Scroll
_hScrollBar.Value = Math.Abs(AutoScrollPosition.X)
AddHandler _hScrollBar.Scroll, AddressOf HorizontalScrollBar_Scroll
End If
End Sub
Protected Overrides Sub OnLocationChanged(e As EventArgs)
MyBase.OnLocationChanged(e)
AdjustVScrollBarLocation()
AdjustHScrollBarLocation()
End Sub
Protected Overrides Sub OnScroll(se As ScrollEventArgs)
MyBase.OnScroll(se)
If se.ScrollOrientation = ScrollOrientation.VerticalScroll Then
If _vScrollBar IsNot Nothing Then
RemoveHandler _vScrollBar.Scroll, AddressOf VerticalScrollBar_Scroll
_vScrollBar.Value = se.NewValue
AddHandler _vScrollBar.Scroll, AddressOf VerticalScrollBar_Scroll
End If
Else
If _hScrollBar IsNot Nothing Then
RemoveHandler _hScrollBar.Scroll, AddressOf HorizontalScrollBar_Scroll
_hScrollBar.Value = se.NewValue
AddHandler _hScrollBar.Scroll, AddressOf HorizontalScrollBar_Scroll
End If
End If
End Sub
Protected Overrides Sub OnVisibleChanged(e As EventArgs)
MyBase.OnVisibleChanged(e)
If Not DesignMode Then
If _vScrollBar IsNot Nothing Then
If Visible Then
_vScrollBar.Visible = VerticalScroll.Visible
Else
If _vScrollBar.Visible Then _vScrollBar.Visible = False
End If
End If
If _hScrollBar IsNot Nothing Then
If Visible Then
_hScrollBar.Visible = HorizontalScroll.Visible
Else
If _hScrollBar.Visible Then _hScrollBar.Visible = False
End If
End If
If Visible Then AutoScrollPosition = New Point(0, 0)
End If
End Sub
Protected Overrides Sub Dispose(disposing As Boolean)
If disposing Then
Try
If _vScrollBar IsNot Nothing Then
Parent.Controls.Remove(_vScrollBar)
_vScrollBar.Dispose()
End If
Catch ex As Exception
'Do nothing
End Try
Try
If _hScrollBar IsNot Nothing Then
Parent.Controls.Remove(_hScrollBar)
_hScrollBar.Dispose()
End If
Catch ex As Exception
'Do nothing
End Try
End If
MyBase.Dispose(disposing)
End Sub
#End Region
#Region "Private Methods"
Private Sub VerticalScrollBar_Scroll(sender As Object, e As ScrollEventArgs)
If _vScrollBar IsNot Nothing Then
AutoScrollPosition = New Point(HorizontalScroll.Value, e.NewValue)
End If
End Sub
Private Sub HorizontalScrollBar_Scroll(sender As Object, e As ScrollEventArgs)
If _hScrollBar IsNot Nothing Then
AutoScrollPosition = New Point(e.NewValue, VerticalScroll.Value)
End If
End Sub
Private Sub AdjustVScrollBarLocation()
If _vScrollBar IsNot Nothing Then
_vScrollBar.Location = If(BorderStyle = BorderStyle.None,
New Point(Location.X + Width - SystemInformation.VerticalScrollBarWidth, Location.Y),
New Point(Location.X + Width - (SystemInformation.VerticalScrollBarWidth + 1), Location.Y + 1))
End If
End Sub
Private Sub AdjustVScrollBarSize()
If _vScrollBar IsNot Nothing Then
Dim h As Integer = Height
If BorderStyle <> BorderStyle.None Then h -= 2
_vScrollBar.Height = h
End If
End Sub
Private Sub AdjustHScrollBarLocation()
If _hScrollBar IsNot Nothing Then
_hScrollBar.Location = If(BorderStyle = BorderStyle.None,
New Point(Location.X, Location.Y + Height - SystemInformation.HorizontalScrollBarHeight),
New Point(Location.X + 1, Location.Y + Height - (SystemInformation.HorizontalScrollBarHeight + 1)))
End If
End Sub
Private Sub AdjustHScrollBarSize()
If _hScrollBar IsNot Nothing Then
Dim w = Width
If BorderStyle <> BorderStyle.None Then w -= 2
If VerticalScroll.Visible Then w -= SystemInformation.VerticalScrollBarWidth
_hScrollBar.Width = w
End If
End Sub
#End Region
#Region "Enumerations"
Private Enum WindowMessage As Integer
WM_CREATE = &H1
WM_NCPAINT = &H85
WM_NCLBUTTONDOWN = &HA1
WM_PAINT = &HF
WM_MOUSEWHEEL = &H20A
WM_NCCALCSIZE = &H83
WM_ERASEBKGND = &H14
WM_SIZE = &H5
WM_PRINTCLIENT = &H318
WM_HSCROLL = &H114
WM_VSCROLL = &H115
End Enum
#End Region
End Class
End Namespace
'Copyright (c) Smart PC Utilities, Ltd.
'All rights reserved.
Public Interface ITheme
#Region "Properties"
''' <summary>
''' Get or set the control style
''' </summary>
Property Theme As UITheme
''' <summary>
''' Get or set whether to allow the control to inherit the parent control style
''' </summary>
Property ParentTheme As Boolean
#End Region
End Interface
@AndnixSH
Copy link

AndnixSH commented May 9, 2023

Can you make this for TabPage?

@ahmedosama007
Copy link
Author

We already made a TabControl control that uses the Flat ScrollBar which is part of our custom UI framework. Unfortunately, I can not share this proprietary code, however, you can use a solution similar to the one used for the Flat Panel to achieve the desired result.

tabpage

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment