Files
Pilz/Pilz.UI.WinForms/Highlighter.vb
2025-06-16 11:50:17 +02:00

407 lines
15 KiB
VB.net

Imports System.ComponentModel
Imports System.Drawing
' Nicht gemergte Änderung aus Projekt "Pilz.UI (net8.0-windows)"
' Vor:
' Imports System.Windows.Forms
' Imports System.Drawing
' Nach:
' Imports System.Drawing
' Imports System.Windows.Forms
Imports System.Windows.Forms
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