401 lines
15 KiB
VB.net
401 lines
15 KiB
VB.net
Imports System
|
|
Imports System.Collections.Generic
|
|
Imports System.ComponentModel
|
|
Imports System.Windows.Forms
|
|
Imports System.Drawing
|
|
|
|
Public Class Highlighter
|
|
Inherits Component
|
|
|
|
Private _Highlights As Dictionary(Of Control, eHighlightColor) = New Dictionary(Of Control, eHighlightColor)()
|
|
Private _HighlightOnFocus As Dictionary(Of Control, Boolean) = New Dictionary(Of Control, Boolean)()
|
|
|
|
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
|
|
If _ContainerControl IsNot Nothing Then
|
|
RemoveHandler _ContainerControl.SizeChanged, AddressOf ContainerControlSizeChanged
|
|
RemoveHandler _ContainerControl.HandleCreated, AddressOf ContainerControlHandleCreated
|
|
End If
|
|
|
|
If _HighlightPanel IsNot Nothing AndAlso _HighlightPanel.Parent Is Nothing AndAlso Not _HighlightPanel.IsDisposed Then
|
|
_HighlightPanel.Dispose()
|
|
_HighlightPanel = Nothing
|
|
Else
|
|
_HighlightPanel = Nothing
|
|
End If
|
|
|
|
MyBase.Dispose(disposing)
|
|
End Sub
|
|
|
|
<DefaultValue(False), Localizable(True), Description("Indicates whether control is highlighted when it receives input focus.")>
|
|
Public Function GetHighlightOnFocus(ByVal c As Control) As Boolean
|
|
If _HighlightOnFocus.ContainsKey(c) Then
|
|
Return _HighlightOnFocus(c)
|
|
End If
|
|
|
|
Return False
|
|
End Function
|
|
|
|
Public Sub SetHighlightOnFocus(ByVal c As Control, ByVal highlight As Boolean)
|
|
If c Is Nothing Then Throw New NullReferenceException()
|
|
|
|
If _HighlightOnFocus.ContainsKey(c) Then
|
|
|
|
If Not highlight Then
|
|
RemoveHighlightOnFocus(_HighlightOnFocus, c)
|
|
End If
|
|
|
|
Return
|
|
End If
|
|
|
|
If highlight Then AddHighlightOnFocus(_HighlightOnFocus, c)
|
|
End Sub
|
|
|
|
Private Sub AddHighlightOnFocus(ByVal highlightOnFocus As Dictionary(Of Control, Boolean), ByVal c As Control)
|
|
AddHandler c.Enter, AddressOf ControlHighlightEnter
|
|
AddHandler c.Leave, AddressOf ControlHighlightLeave
|
|
AddHandler c.VisibleChanged, AddressOf ControlHighlightVisibleChanged
|
|
highlightOnFocus.Add(c, True)
|
|
End Sub
|
|
|
|
Private Sub ControlHighlightVisibleChanged(ByVal sender As Object, ByVal e As EventArgs)
|
|
If _HighlightPanel IsNot Nothing AndAlso _HighlightPanel.FocusHighlightControl = sender Then UpdateHighlighterRegion()
|
|
End Sub
|
|
|
|
Private Sub ControlHighlightLeave(ByVal sender As Object, ByVal e As EventArgs)
|
|
If _HighlightPanel IsNot Nothing Then _HighlightPanel.FocusHighlightControl = Nothing
|
|
UpdateHighlighterRegion()
|
|
End Sub
|
|
|
|
Private Sub ControlHighlightEnter(ByVal sender As Object, ByVal e As EventArgs)
|
|
If _HighlightPanel IsNot Nothing Then
|
|
If Not _HighlightPanel.Visible Then _HighlightPanel.Visible = True
|
|
_HighlightPanel.BringToFront()
|
|
_HighlightPanel.FocusHighlightControl = CType(sender, Control)
|
|
End If
|
|
|
|
UpdateHighlighterRegion()
|
|
End Sub
|
|
|
|
Private Sub RemoveHighlightOnFocus(ByVal highlightOnFocus As Dictionary(Of Control, Boolean), ByVal c As Control)
|
|
RemoveHandler c.Enter, AddressOf ControlHighlightEnter
|
|
RemoveHandler c.Leave, AddressOf ControlHighlightLeave
|
|
RemoveHandler c.VisibleChanged, AddressOf ControlHighlightVisibleChanged
|
|
highlightOnFocus.Remove(c)
|
|
End Sub
|
|
|
|
<DefaultValue(eHighlightColor.None), Localizable(True), Description("Indicates the highlight color that is applied to the control.")>
|
|
Public Function GetHighlightColor(ByVal c As Control) As eHighlightColor
|
|
If _Highlights.ContainsKey(c) Then
|
|
Return _Highlights(c)
|
|
End If
|
|
|
|
Return eHighlightColor.None
|
|
End Function
|
|
|
|
Public Sub SetHighlightColor(ByVal c As Control, ByVal highlightColor As eHighlightColor)
|
|
If _Highlights.ContainsKey(c) Then
|
|
|
|
If highlightColor = eHighlightColor.None Then
|
|
RemoveHighlight(_Highlights, c)
|
|
Else
|
|
Dim color As eHighlightColor = _Highlights(c)
|
|
RemoveHighlight(_Highlights, c)
|
|
AddHighlight(_Highlights, c, highlightColor)
|
|
End If
|
|
ElseIf highlightColor <> eHighlightColor.None Then
|
|
AddHighlight(_Highlights, c, highlightColor)
|
|
End If
|
|
End Sub
|
|
|
|
Private _TabControl2 As Dictionary(Of System.Windows.Forms.TabControl, Integer) = New Dictionary(Of System.Windows.Forms.TabControl, Integer)()
|
|
Private _ParentPanel As Dictionary(Of Panel, Integer) = New Dictionary(Of Panel, Integer)()
|
|
|
|
Private Sub AddHighlight(ByVal highlights As Dictionary(Of Control, eHighlightColor), ByVal c As Control, ByVal highlightColor As eHighlightColor)
|
|
highlights.Add(c, highlightColor)
|
|
AddHandler c.LocationChanged, New EventHandler(AddressOf ControlLocationChanged)
|
|
AddHandler c.SizeChanged, New EventHandler(AddressOf ControlSizeChanged)
|
|
AddHandler c.VisibleChanged, New EventHandler(AddressOf ControlVisibleChanged)
|
|
|
|
If _HighlightPanel IsNot Nothing Then
|
|
If Not _HighlightPanel.Visible Then _HighlightPanel.Visible = True
|
|
_HighlightPanel.BringToFront()
|
|
End If
|
|
|
|
If c.Parent Is Nothing Then
|
|
AddHandler c.ParentChanged, AddressOf ControlParentChanged
|
|
Else
|
|
AddTabControlHandlers(c)
|
|
End If
|
|
|
|
UpdateHighlighterRegion()
|
|
End Sub
|
|
|
|
Private Sub ControlParentChanged(ByVal sender As Object, ByVal e As EventArgs)
|
|
Dim c As Control = CType(sender, Control)
|
|
RemoveHandler c.ParentChanged, AddressOf ControlParentChanged
|
|
AddTabControlHandlers(c)
|
|
End Sub
|
|
|
|
Private Sub AddTabControlHandlers(ByVal c As Control)
|
|
Dim tab2 As System.Windows.Forms.TabControl = TryCast(GetParentControl(c, GetType(System.Windows.Forms.TabControl)), System.Windows.Forms.TabControl)
|
|
|
|
If tab2 IsNot Nothing Then
|
|
|
|
If _TabControl2.ContainsKey(tab2) Then
|
|
_TabControl2(tab2) = _TabControl2(tab2) + 1
|
|
Else
|
|
_TabControl2.Add(tab2, 1)
|
|
AddHandler tab2.SelectedIndexChanged, AddressOf WinFormsTabSelectedIndexChanged
|
|
End If
|
|
Else
|
|
Dim parentPanel As Panel = TryCast(GetParentControl(c, GetType(Panel)), Panel)
|
|
|
|
If parentPanel IsNot Nothing Then
|
|
|
|
If _ParentPanel.ContainsKey(parentPanel) Then
|
|
_ParentPanel(parentPanel) = _ParentPanel(parentPanel) + 1
|
|
Else
|
|
_ParentPanel.Add(parentPanel, 1)
|
|
AddHandler parentPanel.Resize, AddressOf ParentPanelResized
|
|
AddHandler parentPanel.LocationChanged, AddressOf ParentPanelLocationChanged
|
|
End If
|
|
End If
|
|
End If
|
|
End Sub
|
|
|
|
Private Sub ParentPanelLocationChanged(ByVal sender As Object, ByVal e As EventArgs)
|
|
UpdateHighlights()
|
|
End Sub
|
|
|
|
Private Sub ParentPanelResized(ByVal sender As Object, ByVal e As EventArgs)
|
|
UpdateHighlights()
|
|
End Sub
|
|
|
|
Private Sub WinFormsTabSelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs)
|
|
UpdateHighlighterRegion()
|
|
End Sub
|
|
|
|
Private Function GetParentControl(ByVal c As Control, ByVal parentType As Type) As Control
|
|
Dim parent As Control = c.Parent
|
|
|
|
While parent IsNot Nothing
|
|
If parentType.IsAssignableFrom(parent.[GetType]()) Then Return parent
|
|
parent = parent.Parent
|
|
End While
|
|
|
|
Return Nothing
|
|
End Function
|
|
|
|
Private Sub ControlVisibleChanged(ByVal sender As Object, ByVal e As EventArgs)
|
|
UpdateHighlighterRegion()
|
|
End Sub
|
|
|
|
Private Sub ControlSizeChanged(ByVal sender As Object, ByVal e As EventArgs)
|
|
UpdateHighlighterRegion()
|
|
End Sub
|
|
|
|
Private Sub ControlLocationChanged(ByVal sender As Object, ByVal e As EventArgs)
|
|
UpdateHighlighterRegion()
|
|
End Sub
|
|
|
|
Private Sub UpdateHighlighterRegion()
|
|
If _HighlightPanel IsNot Nothing Then _HighlightPanel.UpdateRegion()
|
|
End Sub
|
|
|
|
Public Sub UpdateHighlights()
|
|
UpdateHighlighterRegion()
|
|
End Sub
|
|
|
|
Private Sub RemoveHighlight(ByVal highlights As Dictionary(Of Control, eHighlightColor), ByVal c As Control)
|
|
highlights.Remove(c)
|
|
RemoveHandler c.LocationChanged, New EventHandler(AddressOf ControlLocationChanged)
|
|
RemoveHandler c.SizeChanged, New EventHandler(AddressOf ControlSizeChanged)
|
|
RemoveHandler c.VisibleChanged, New EventHandler(AddressOf ControlVisibleChanged)
|
|
Dim tab2 As System.Windows.Forms.TabControl = TryCast(GetParentControl(c, GetType(System.Windows.Forms.TabControl)), System.Windows.Forms.TabControl)
|
|
|
|
If tab2 IsNot Nothing Then
|
|
|
|
If _TabControl2.ContainsKey(tab2) Then
|
|
|
|
If _TabControl2(tab2) = 1 Then
|
|
_TabControl2.Remove(tab2)
|
|
RemoveHandler tab2.SelectedIndexChanged, AddressOf WinFormsTabSelectedIndexChanged
|
|
Else
|
|
_TabControl2(tab2) = _TabControl2(tab2) - 1
|
|
End If
|
|
End If
|
|
Else
|
|
Dim parentPanel As Panel = TryCast(GetParentControl(c, GetType(Panel)), Panel)
|
|
|
|
If parentPanel IsNot Nothing Then
|
|
|
|
If _ParentPanel.ContainsKey(parentPanel) Then
|
|
|
|
If _ParentPanel(parentPanel) = 1 Then
|
|
_ParentPanel.Remove(parentPanel)
|
|
RemoveHandler parentPanel.LocationChanged, AddressOf ParentPanelLocationChanged
|
|
RemoveHandler parentPanel.SizeChanged, AddressOf ParentPanelResized
|
|
Else
|
|
_ParentPanel(parentPanel) = _ParentPanel(parentPanel) - 1
|
|
End If
|
|
End If
|
|
End If
|
|
End If
|
|
|
|
UpdateHighlighterRegion()
|
|
End Sub
|
|
|
|
Friend ReadOnly Property Highlights As Dictionary(Of Control, eHighlightColor)
|
|
Get
|
|
Return _Highlights
|
|
End Get
|
|
End Property
|
|
|
|
Private _FocusHighlightColor As eHighlightColor = eHighlightColor.Blue
|
|
|
|
<DefaultValue(eHighlightColor.Blue), Category("Appearance"), Description("Indicates the highlight focus color."), Localizable(True)>
|
|
Public Property FocusHighlightColor As eHighlightColor
|
|
Get
|
|
Return _FocusHighlightColor
|
|
End Get
|
|
Set(ByVal value As eHighlightColor)
|
|
_FocusHighlightColor = value
|
|
|
|
If _HighlightPanel IsNot Nothing Then
|
|
_HighlightPanel.FocusHighlightColor = value
|
|
UpdateHighlighterRegion()
|
|
End If
|
|
End Set
|
|
End Property
|
|
|
|
Private _HighlightPanel As HighlightPanel = Nothing
|
|
Private _ContainerControl As Control = Nothing
|
|
|
|
<Description("Indicates container control highlighter is bound to. Should be set to parent form."), Category("Behavior")>
|
|
Public Property ContainerControl As Control
|
|
Get
|
|
Return _ContainerControl
|
|
End Get
|
|
Set(ByVal value As Control)
|
|
|
|
If Me.DesignMode Then
|
|
_ContainerControl = value
|
|
Return
|
|
End If
|
|
|
|
If _ContainerControl IsNot value Then
|
|
|
|
If _ContainerControl IsNot Nothing Then
|
|
RemoveHandler _ContainerControl.SizeChanged, AddressOf ContainerControlSizeChanged
|
|
RemoveHandler _ContainerControl.HandleCreated, AddressOf ContainerControlHandleCreated
|
|
If _HighlightPanel IsNot Nothing AndAlso _HighlightPanel.Parent Is _ContainerControl Then _ContainerControl.Controls.Remove(_HighlightPanel)
|
|
End If
|
|
|
|
_ContainerControl = value
|
|
|
|
If _ContainerControl IsNot Nothing Then
|
|
|
|
If _HighlightPanel Is Nothing Then
|
|
_HighlightPanel = New HighlightPanel(_Highlights)
|
|
_HighlightPanel.FocusHighlightColor = _FocusHighlightColor
|
|
_HighlightPanel.Margin = New System.Windows.Forms.Padding(0)
|
|
_HighlightPanel.Padding = New System.Windows.Forms.Padding(0)
|
|
_HighlightPanel.CustomHighlightColors = _CustomHighlightColors
|
|
_HighlightPanel.Visible = False
|
|
End If
|
|
|
|
AddHandler _ContainerControl.SizeChanged, AddressOf ContainerControlSizeChanged
|
|
AddHandler _ContainerControl.HandleCreated, AddressOf ContainerControlHandleCreated
|
|
_ContainerControl.Controls.Add(_HighlightPanel)
|
|
UpdateHighlightPanelBounds()
|
|
End If
|
|
End If
|
|
End Set
|
|
End Property
|
|
|
|
Private Sub ContainerControlHandleCreated(ByVal sender As Object, ByVal e As EventArgs)
|
|
If _Highlights.Count > 0 AndAlso _HighlightPanel IsNot Nothing AndAlso Not _HighlightPanel.Visible Then _HighlightPanel.Visible = True
|
|
End Sub
|
|
|
|
Private Sub UpdateHighlightPanelBounds()
|
|
Dim bounds As Rectangle = New Rectangle(0, 0, _ContainerControl.ClientRectangle.Width, _ContainerControl.ClientRectangle.Height)
|
|
|
|
If _HighlightPanel IsNot Nothing Then
|
|
If TypeOf _HighlightPanel.Parent Is Form Then
|
|
Dim form As Form = TryCast(_HighlightPanel.Parent, Form)
|
|
|
|
If form.AutoSize Then
|
|
bounds.X += form.Padding.Left
|
|
bounds.Y += form.Padding.Top
|
|
bounds.Width -= form.Padding.Horizontal
|
|
bounds.Height -= form.Padding.Vertical
|
|
End If
|
|
End If
|
|
|
|
If _HighlightPanel.Bounds.Equals(bounds) Then
|
|
_HighlightPanel.UpdateRegion()
|
|
Else
|
|
_HighlightPanel.Bounds = bounds
|
|
End If
|
|
|
|
_HighlightPanel.BringToFront()
|
|
End If
|
|
End Sub
|
|
|
|
Private _DelayTimer As Timer = Nothing
|
|
|
|
Private Sub ContainerControlSizeChanged(ByVal sender As Object, ByVal e As EventArgs)
|
|
Dim form As Form = TryCast(sender, Form)
|
|
|
|
If form IsNot Nothing Then
|
|
|
|
If _DelayTimer Is Nothing Then
|
|
_DelayTimer = New Timer()
|
|
_DelayTimer.Interval = 100
|
|
AddHandler _DelayTimer.Tick, New EventHandler(AddressOf DelayTimerTick)
|
|
_DelayTimer.Start()
|
|
End If
|
|
|
|
Return
|
|
End If
|
|
|
|
UpdateHighlightPanelBounds()
|
|
End Sub
|
|
|
|
Private Sub DelayTimerTick(ByVal sender As Object, ByVal e As EventArgs)
|
|
Dim timer As Timer = _DelayTimer
|
|
_DelayTimer = Nothing
|
|
RemoveHandler timer.Tick, New EventHandler(AddressOf DelayTimerTick)
|
|
timer.[Stop]()
|
|
timer.Dispose()
|
|
UpdateHighlightPanelBounds()
|
|
End Sub
|
|
|
|
Private _CustomHighlightColors As Color() = Nothing
|
|
|
|
<Category("Appearance"), Description("Array of colors used to render custom highlight color. Control expects 3 colors in array to be specified which define the highlight border.")>
|
|
Public Property CustomHighlightColors As Color()
|
|
Get
|
|
Return _CustomHighlightColors
|
|
End Get
|
|
Set(ByVal value As Color())
|
|
_CustomHighlightColors = value
|
|
|
|
If _HighlightPanel IsNot Nothing Then
|
|
_HighlightPanel.CustomHighlightColors = _CustomHighlightColors
|
|
_HighlightPanel.Invalidate()
|
|
End If
|
|
End Set
|
|
End Property
|
|
|
|
End Class
|
|
|
|
Public Enum eHighlightColor
|
|
None
|
|
Red
|
|
Blue
|
|
Green
|
|
Orange
|
|
Custom
|
|
End Enum
|