Skip to content

Instantly share code, notes, and snippets.

@ahmedosama007
Last active July 21, 2022 04:15
Show Gist options
  • Save ahmedosama007/d40ec7c1a742b831b1a69f5ce776db7a to your computer and use it in GitHub Desktop.
Save ahmedosama007/d40ec7c1a742b831b1a69f5ce776db7a to your computer and use it in GitHub Desktop.
Custom Form control buttons that support the Visual Studio 2019 theme
#Region "References"
Imports System.ComponentModel
Imports System.Drawing.Drawing2D
#End Region
Namespace Controls
<ToolboxItem(True)> <ToolboxBitmap(GetType(Button))> Public Class FormControlButton
Inherits NoFocusCueButton
#Region "Private Members"
Private _theme As UITheme = UITheme.VS2019LightBlue
Private _iconPen As Pen
Private _iconBrush As Brush
Private _iconColor As Color = Color.FromArgb(30, 30, 30)
Private _buttonType As ControlButtonType = ControlButtonType.Close
Private _isMouseDown, _isMouseEntered As Boolean
#End Region
#Region "Constructor"
Public Sub New()
SetStyle(ControlStyles.UserPaint Or ControlStyles.AllPaintingInWmPaint Or ControlStyles.OptimizedDoubleBuffer Or ControlStyles.ResizeRedraw, True)
BackColor = Color.FromArgb(251, 251, 251)
End Sub
#End Region
#Region "Enumerations"
Public Enum ControlButtonType
''' <summary>
''' Button to close the Form
''' </summary>
Close
''' <summary>
''' Button to maximize the Form
''' </summary>
Maximize
''' <summary>
''' Button to minimize the Form
''' </summary>
Minimize
''' <summary>
''' Button to show the app settings/options
''' </summary>
Menu
End Enum
#End Region
#Region "Public Properties"
<Category("Appearance")> <Description("The background color of the Control Button in the Normal state.")>
<DefaultValue(GetType(Color), "251, 251, 251")> Public Overrides Property BackColor As Color
Get
Return MyBase.BackColor
End Get
Set(value As Color)
MyBase.BackColor = value
End Set
End Property
<EditorBrowsable(EditorBrowsableState.Always)>
<Browsable(True)> <DefaultValue(GetType(ControlButtonType), "0")>
<Category("Appearance")> <Description("The Control Button type.")>
Public Property ButtonType As ControlButtonType
Get
Return _buttonType
End Get
Set(value As ControlButtonType)
_buttonType = value
Invalidate()
End Set
End Property
<EditorBrowsable(EditorBrowsableState.Always)>
<Browsable(True)> <DefaultValue(GetType(Color), "255, 255, 255")>
<Category("Appearance")> <Description("The background color of the Control Button when the mouse enters the button.")>
Public Property MouseHoverBackColor As Color = Color.FromArgb(255, 255, 255)
<EditorBrowsable(EditorBrowsableState.Always)>
<Browsable(True)> <DefaultValue(GetType(Color), "0, 122, 204")>
<Category("Appearance")> <Description("The background color of the Control Button when the button is clicked.")>
Public Property MouseDownBackColor As Color = Color.FromArgb(0, 122, 204)
<EditorBrowsable(EditorBrowsableState.Always)>
<Browsable(True)> <DefaultValue(GetType(Color), "30, 30, 30")>
<Category("Appearance")> <Description("The Control Button icon color.")>
Public Property IconColor As Color
Get
Return _iconColor
End Get
Set(value As Color)
_iconColor = value
Invalidate()
End Set
End Property
<EditorBrowsable(EditorBrowsableState.Always)>
<Browsable(True)> <DefaultValue(GetType(Color), "0, 122, 204")>
<Category("Appearance")> <Description("The color of the Control Button icon when the mouse enters the button.")>
Public Property MouseHoverIconColor As Color = Color.FromArgb(0, 122, 204)
<EditorBrowsable(EditorBrowsableState.Always)>
<Browsable(True)> <DefaultValue(GetType(Color), "255, 255, 255")>
<Category("Appearance")> <Description("The color of the Control Button icon when the button is clicked.")>
Public Property MouseDownIconColor As Color = Color.FromArgb(255, 255, 255)
<Category("Appearance")> <Description("The theme to apply to the Control Button.")> <DefaultValue(GetType(UITheme), "1")> Public Property Theme As UITheme
Get
Return _theme
End Get
Set(value As UITheme)
_theme = value
If _theme = UITheme.VS2019DarkBlue Then
BackColor = Color.FromArgb(37, 37, 38)
If _buttonType = ControlButtonType.Close Then
MouseHoverBackColor = Color.FromArgb(232, 17, 35)
MouseDownBackColor = Color.FromArgb(241, 112, 122)
MouseHoverIconColor = Color.FromArgb(255, 255, 255)
Else
MouseHoverBackColor = Color.FromArgb(63, 63, 64)
MouseDownBackColor = Color.FromArgb(0, 122, 204)
MouseHoverIconColor = Color.FromArgb(255, 255, 255)
End If
IconColor = Color.FromArgb(241, 241, 241)
MouseDownIconColor = Color.FromArgb(255, 255, 255)
ElseIf _theme = UITheme.VS2019LightBlue Then
BackColor = Color.FromArgb(251, 251, 251)
If _buttonType = ControlButtonType.Close Then
MouseHoverBackColor = Color.FromArgb(232, 17, 35)
MouseDownBackColor = Color.FromArgb(241, 112, 122)
MouseHoverIconColor = Color.FromArgb(255, 255, 255)
Else
MouseHoverBackColor = Color.FromArgb(255, 255, 255)
MouseDownBackColor = Color.FromArgb(0, 122, 204)
MouseHoverIconColor = Color.FromArgb(0, 122, 204)
End If
IconColor = Color.FromArgb(30, 30, 30)
MouseDownIconColor = Color.FromArgb(255, 255, 255)
End If
Invalidate()
End Set
End Property
Protected Overrides ReadOnly Property DefaultSize As Size
Get
Return New Size(46, 30)
End Get
End Property
#End Region
#Region "Private Properties"
Private ReadOnly Property ActiveBackColor As Color
Get
If _isMouseDown Then Return MouseDownBackColor
If _isMouseEntered Then Return MouseHoverBackColor
Return BackColor
End Get
End Property
Private ReadOnly Property ActiveIconColor As Color
Get
If _isMouseDown Then Return MouseDownIconColor
If _isMouseEntered Then Return MouseHoverIconColor
Return IconColor
End Get
End Property
#End Region
#Region "Overriden Methods"
Protected Overrides Sub OnClick(e As EventArgs)
If _buttonType <> ControlButtonType.Menu Then
Dim frm As Form = FindForm()
If frm IsNot Nothing Then
If _buttonType = ControlButtonType.Close Then
frm.Close()
ElseIf _buttonType = ControlButtonType.Maximize Then
frm.WindowState = If(frm.WindowState = FormWindowState.Maximized, FormWindowState.Normal, FormWindowState.Maximized)
Else
frm.WindowState = FormWindowState.Minimized
End If
End If
End If
MyBase.OnClick(e)
End Sub
Protected Overrides Sub OnPaint(pevent As PaintEventArgs)
Using sb = New SolidBrush(ActiveBackColor)
pevent.Graphics.FillRectangle(sb, pevent.ClipRectangle)
End Using
pevent.Graphics.SmoothingMode = SmoothingMode.HighQuality
_iconBrush?.Dispose()
_iconPen?.Dispose()
_iconBrush = New SolidBrush(ActiveIconColor)
_iconPen = New Pen(_iconBrush, 1.0F)
If _buttonType = ControlButtonType.Close Then
DrawCloseIcon(pevent)
ElseIf _buttonType = ControlButtonType.Maximize Then
DrawMaximizeIcon(pevent)
ElseIf _buttonType = ControlButtonType.Minimize Then
DrawMinimizeIcon(pevent)
ElseIf _buttonType = ControlButtonType.Menu Then
DrawMenuIcon(pevent)
End If
End Sub
Protected Overrides Sub OnMouseEnter(e As EventArgs)
MyBase.OnMouseEnter(e)
If Not DesignMode Then _isMouseEntered = True
End Sub
Protected Overrides Sub OnMouseLeave(e As EventArgs)
MyBase.OnMouseLeave(e)
If Not DesignMode Then _isMouseEntered = False
End Sub
Protected Overrides Sub OnMouseDown(mevent As MouseEventArgs)
MyBase.OnMouseDown(mevent)
If Not DesignMode Then _isMouseDown = True
End Sub
Protected Overrides Sub OnMouseUp(mevent As MouseEventArgs)
MyBase.OnMouseUp(mevent)
If Not DesignMode Then _isMouseDown = False
End Sub
#End Region
#Region "Private Methods"
Private Sub DrawCloseIcon(e As PaintEventArgs)
Dim drawRect = ClientRectangle
e.Graphics.DrawLine(_iconPen, CInt(drawRect.X + (drawRect.Width / 2) - 5), CInt(drawRect.Y + (drawRect.Height / 2) - 5), CInt(drawRect.X + (drawRect.Width / 2) + 5), CInt(drawRect.Y + (drawRect.Height / 2) + 5))
e.Graphics.DrawLine(_iconPen, CInt(drawRect.X + (drawRect.Width / 2) - 5), CInt(drawRect.Y + (drawRect.Height / 2) + 5), CInt(drawRect.X + (drawRect.Width / 2) + 5), CInt(drawRect.Y + (drawRect.Height / 2) - 5))
End Sub
Private Sub DrawMaximizeIcon(e As PaintEventArgs)
Dim drawRect = ClientRectangle
Dim frm = FindForm()
If frm IsNot Nothing Then
If frm.WindowState = FormWindowState.Maximized Then
e.Graphics.DrawRectangle(_iconPen, New Rectangle(CInt(drawRect.X + (drawRect.Width / 2) - 3), CInt(drawRect.Y + (drawRect.Height / 2) - 5), 8, 8))
Dim rect As New Rectangle(CInt(drawRect.X + (drawRect.Width / 2) - 5), CInt(drawRect.Y + (drawRect.Height / 2) - 3), 8, 8)
Using sb = New SolidBrush(ActiveBackColor)
e.Graphics.FillRectangle(sb, rect)
End Using
e.Graphics.DrawRectangle(_iconPen, rect)
Else
e.Graphics.DrawRectangle(_iconPen, New Rectangle(CInt(drawRect.X + (drawRect.Width / 2) - 5), CInt(drawRect.Y + (drawRect.Height / 2) - 5), 10, 10))
End If
End If
End Sub
Private Sub DrawMinimizeIcon(e As PaintEventArgs)
Dim drawRect = ClientRectangle
e.Graphics.DrawLine(_iconPen, CInt(drawRect.X + (drawRect.Width / 2) - 5), CInt(drawRect.Y + (drawRect.Height / 2)), CInt(drawRect.X + (drawRect.Width / 2) + 5), CInt(drawRect.Y + (drawRect.Height / 2)))
End Sub
Private Sub DrawMenuIcon(e As PaintEventArgs)
Dim drawRect = ClientRectangle
Dim vMargin As Integer = 4
e.Graphics.DrawLine(_iconPen, CInt(drawRect.X + (drawRect.Width / 2) - 5), CInt(drawRect.Y + (drawRect.Height / 2) - vMargin), CInt(drawRect.X + (drawRect.Width / 2) + 5), CInt(drawRect.Y + (drawRect.Height / 2) - vMargin))
e.Graphics.DrawLine(_iconPen, CInt(drawRect.X + (drawRect.Width / 2) - 5), CInt(drawRect.Y + (drawRect.Height / 2)), CInt(drawRect.X + (drawRect.Width / 2) + 5), CInt(drawRect.Y + (drawRect.Height / 2)))
e.Graphics.DrawLine(_iconPen, CInt(drawRect.X + (drawRect.Width / 2) - 5), CInt(drawRect.Y + (drawRect.Height / 2) + vMargin), CInt(drawRect.X + (drawRect.Width / 2) + 5), CInt(drawRect.Y + (drawRect.Height / 2) + vMargin))
End Sub
#End Region
End Class
End Namespace
Namespace Controls
<ToolboxBitmap(GetType(Button))> Public Class NoFocusCueButton
Inherits Button
#Region "Constructor"
Public Sub New()
MyBase.New()
SetStyle(ControlStyles.Selectable, False)
End Sub
#End Region
#Region "Overrides"
Protected Overrides ReadOnly Property ShowFocusCues As Boolean
Get
Return False
End Get
End Property
Public Overrides Sub NotifyDefault(value As Boolean)
MyBase.NotifyDefault(False)
End Sub
#End Region
End Class
End Namespace
Public Enum UITheme As Integer
''' <summary>
''' User defined theme
''' </summary>
Custom = -1
''' <summary>
''' Visual Studio 2019 Dark Blue theme
''' </summary>
VS2019DarkBlue = 0
''' <summary>
''' Visual Studio 2019 Light Blue theme
''' </summary>
VS2019LightBlue = 1
End Enum
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment