Advertisement
modernaesthetics

Graph Control - VB.NET

Jun 7th, 2018
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
VB.NET 19.56 KB | None | 0 0
  1. Imports System.Drawing.Drawing2D
  2.  
  3. '------------------
  4. 'Creator: aeonhack
  5. 'Site: elitevs.net
  6. 'Created: 08/18/2012
  7. 'Changed: 01/16/2013
  8. 'Version: 1.3.0
  9. '------------------
  10. Public Class Graph
  11.     Inherits Control
  12.  
  13.     Sub New()
  14.         Dim B As New Bitmap(1, 1)
  15.         SG = Graphics.FromImage(B)
  16.  
  17.         GP = New GraphicsPath()
  18.         _Values = New List(Of Single)
  19.         _SmoothValues = New List(Of Single)
  20.  
  21.         FillColor = Color.White
  22.         BorderColor = Color.Gray
  23.  
  24.         GraphFillColor = Color.FromArgb(50, Color.LightGreen)
  25.         GraphBorderColor = Color.ForestGreen
  26.  
  27.         HorizontalLineColor = Color.FromArgb(238, 238, 238)
  28.         VerticalLineColor = Color.FromArgb(248, 248, 248)
  29.  
  30.         DataColumnForeColor = Color.Gray
  31.  
  32.         HoverFillColor = Color.White
  33.         HoverBorderColor = Color.ForestGreen
  34.         HoverLineColor = Color.FromArgb(35, Color.ForestGreen)
  35.  
  36.         HoverLabelForeColor = Color.Gray
  37.         HoverLabelFillColor = Color.White
  38.         HoverLabelBorderColor = Color.DarkGray
  39.         HoverLabelShadowColor = Color.FromArgb(35, Color.Black)
  40.  
  41.         LineGraphColor = Color.FromArgb(130, 0, 200, 255)
  42.  
  43.         SetStyle(DirectCast(139286, ControlStyles), True)
  44.     End Sub
  45.  
  46. #Region " Properties "
  47.  
  48.     Private _FillColor As SolidBrush
  49.     Public Property FillColor() As Color
  50.         Get
  51.             Return _FillColor.Color
  52.         End Get
  53.         Set(ByVal value As Color)
  54.             _FillColor = New SolidBrush(value)
  55.             Invalidate()
  56.         End Set
  57.     End Property
  58.  
  59.     Private _BorderColor As Pen
  60.     Public Property BorderColor() As Color
  61.         Get
  62.             Return _BorderColor.Color
  63.         End Get
  64.         Set(ByVal value As Color)
  65.             _BorderColor = New Pen(value)
  66.             Invalidate()
  67.         End Set
  68.     End Property
  69.  
  70.     Private _GraphFillColor As SolidBrush
  71.     Public Property GraphFillColor() As Color
  72.         Get
  73.             Return _GraphFillColor.Color
  74.         End Get
  75.         Set(ByVal value As Color)
  76.             _GraphFillColor = New SolidBrush(value)
  77.             Invalidate()
  78.         End Set
  79.     End Property
  80.  
  81.     Private _GraphBorderColor As Pen
  82.     Public Property GraphBorderColor() As Color
  83.         Get
  84.             Return _GraphBorderColor.Color
  85.         End Get
  86.         Set(ByVal value As Color)
  87.             _GraphBorderColor = New Pen(value)
  88.             Invalidate()
  89.         End Set
  90.     End Property
  91.  
  92.     Private _HorizontalLineColor As Pen
  93.     Public Property HorizontalLineColor() As Color
  94.         Get
  95.             Return _HorizontalLineColor.Color
  96.         End Get
  97.         Set(ByVal value As Color)
  98.             _HorizontalLineColor = New Pen(value)
  99.             Invalidate()
  100.         End Set
  101.     End Property
  102.  
  103.     Private _VerticalLineColor As Pen
  104.     Public Property VerticalLineColor() As Color
  105.         Get
  106.             Return _VerticalLineColor.Color
  107.         End Get
  108.         Set(ByVal value As Color)
  109.             _VerticalLineColor = New Pen(value)
  110.             Invalidate()
  111.         End Set
  112.     End Property
  113.  
  114.     Private _DataColumnForeColor As SolidBrush
  115.     Public Property DataColumnForeColor() As Color
  116.         Get
  117.             Return _DataColumnForeColor.Color
  118.         End Get
  119.         Set(ByVal value As Color)
  120.             _DataColumnForeColor = New SolidBrush(value)
  121.             Invalidate()
  122.         End Set
  123.     End Property
  124.  
  125.     Private _HoverFillColor As SolidBrush
  126.     Public Property HoverFillColor() As Color
  127.         Get
  128.             Return _HoverFillColor.Color
  129.         End Get
  130.         Set(ByVal value As Color)
  131.             _HoverFillColor = New SolidBrush(value)
  132.             Invalidate()
  133.         End Set
  134.     End Property
  135.  
  136.     Private _HoverBorderColor As Pen
  137.     Public Property HoverBorderColor() As Color
  138.         Get
  139.             Return _HoverBorderColor.Color
  140.         End Get
  141.         Set(ByVal value As Color)
  142.             _HoverBorderColor = New Pen(value)
  143.             Invalidate()
  144.         End Set
  145.     End Property
  146.  
  147.     Private _HoverLineColor As Pen
  148.     Public Property HoverLineColor() As Color
  149.         Get
  150.             Return _HoverLineColor.Color
  151.         End Get
  152.         Set(ByVal value As Color)
  153.             _HoverLineColor = New Pen(value)
  154.             Invalidate()
  155.         End Set
  156.     End Property
  157.  
  158.     Private _HoverLabelForeColor As SolidBrush
  159.     Public Property HoverLabelForeColor() As Color
  160.         Get
  161.             Return _HoverLabelForeColor.Color
  162.         End Get
  163.         Set(ByVal value As Color)
  164.             _HoverLabelForeColor = New SolidBrush(value)
  165.             Invalidate()
  166.         End Set
  167.     End Property
  168.  
  169.     Private _HoverLabelFillColor As SolidBrush
  170.     Public Property HoverLabelFillColor() As Color
  171.         Get
  172.             Return _HoverLabelFillColor.Color
  173.         End Get
  174.         Set(ByVal value As Color)
  175.             _HoverLabelFillColor = New SolidBrush(value)
  176.             Invalidate()
  177.         End Set
  178.     End Property
  179.  
  180.     Private _HoverLabelBorderColor As Pen
  181.     Public Property HoverLabelBorderColor() As Color
  182.         Get
  183.             Return _HoverLabelBorderColor.Color
  184.         End Get
  185.         Set(ByVal value As Color)
  186.             _HoverLabelBorderColor = New Pen(value)
  187.             Invalidate()
  188.         End Set
  189.     End Property
  190.  
  191.     Private _HoverLabelShadowColor As Pen
  192.     Public Property HoverLabelShadowColor() As Color
  193.         Get
  194.             Return _HoverLabelShadowColor.Color
  195.         End Get
  196.         Set(ByVal value As Color)
  197.             _HoverLabelShadowColor = New Pen(value, 2)
  198.             Invalidate()
  199.         End Set
  200.     End Property
  201.  
  202.     Private _LineGraphColor As Pen
  203.     Public Property LineGraphColor() As Color
  204.         Get
  205.             Return _LineGraphColor.Color
  206.         End Get
  207.         Set(ByVal value As Color)
  208.             _LineGraphColor = New Pen(value, 6)
  209.             _LineGraphColor.MiterLimit = 0.0F
  210.             Invalidate()
  211.         End Set
  212.     End Property
  213.  
  214.     Private _DrawLineGraph As Boolean
  215.     Public Property DrawLineGraph() As Boolean
  216.         Get
  217.             Return _DrawLineGraph
  218.         End Get
  219.         Set(ByVal value As Boolean)
  220.             _DrawLineGraph = value
  221.             Invalidate()
  222.         End Set
  223.     End Property
  224.  
  225.     Private _SidePadding As Boolean = True
  226.     Public Property SidePadding() As Boolean
  227.         Get
  228.             Return _SidePadding
  229.         End Get
  230.         Set(ByVal value As Boolean)
  231.             _SidePadding = value
  232.             Invalidate()
  233.         End Set
  234.     End Property
  235.  
  236.     Private _DrawHoverData As Boolean = True
  237.     Public Property DrawHoverData() As Boolean
  238.         Get
  239.             Return _DrawHoverData
  240.         End Get
  241.         Set(ByVal value As Boolean)
  242.             Index = -1
  243.             _DrawHoverData = value
  244.             Invalidate()
  245.         End Set
  246.     End Property
  247.  
  248.     Private _DrawHoverLine As Boolean = True
  249.     Public Property DrawHoverLine() As Boolean
  250.         Get
  251.             Return _DrawHoverLine
  252.         End Get
  253.         Set(ByVal value As Boolean)
  254.             _DrawHoverLine = value
  255.             Invalidate()
  256.         End Set
  257.     End Property
  258.  
  259.     Private _DrawDataColumn As Boolean = True
  260.     Public Property DrawDataColumn() As Boolean
  261.         Get
  262.             Return _DrawDataColumn
  263.         End Get
  264.         Set(ByVal value As Boolean)
  265.             _DrawDataColumn = value
  266.             Invalidate()
  267.         End Set
  268.     End Property
  269.  
  270.     Private _DrawHorizontalLines As Boolean = True
  271.     Public Property DrawHorizontalLines() As Boolean
  272.         Get
  273.             Return _DrawHorizontalLines
  274.         End Get
  275.         Set(ByVal value As Boolean)
  276.             _DrawHorizontalLines = value
  277.             Invalidate()
  278.         End Set
  279.     End Property
  280.  
  281.     Private _DrawVerticalLines As Boolean
  282.     Public Property DrawVerticalLines() As Boolean
  283.         Get
  284.             Return _DrawVerticalLines
  285.         End Get
  286.         Set(ByVal value As Boolean)
  287.             _DrawVerticalLines = value
  288.             Invalidate()
  289.         End Set
  290.     End Property
  291.  
  292.     Private _DataSmoothing As Boolean
  293.     Public Property DataSmoothing() As Boolean
  294.         Get
  295.             Return _DataSmoothing
  296.         End Get
  297.         Set(ByVal value As Boolean)
  298.             _DataSmoothing = value
  299.  
  300.             InvalidateSmoothValues()
  301.             FindMinMax()
  302.  
  303.             Invalidate()
  304.         End Set
  305.     End Property
  306.  
  307.     Private _DataSmoothingLevel As Byte = 2
  308.     Public Property DataSmoothingLevel() As Byte
  309.         Get
  310.             Return _DataSmoothingLevel
  311.         End Get
  312.         Set(ByVal value As Byte)
  313.             If value < 1 Then value = 1
  314.  
  315.             _DataSmoothingLevel = value
  316.  
  317.             InvalidateSmoothValues()
  318.             FindMinMax()
  319.  
  320.             Invalidate()
  321.         End Set
  322.     End Property
  323.  
  324.     Public ReadOnly Property MaximumValue() As Single
  325.         Get
  326.             Return _MaximumValue
  327.         End Get
  328.     End Property
  329.  
  330.     Public ReadOnly Property MinimumValue() As Single
  331.         Get
  332.             Return _MinimumValue
  333.         End Get
  334.     End Property
  335.  
  336.     Private _OverrideMin As Boolean = False
  337.     Public Property OverrideMin() As Boolean
  338.         Get
  339.             Return _OverrideMin
  340.         End Get
  341.         Set(ByVal value As Boolean)
  342.             _OverrideMin = value
  343.             If value Then InvalidateMinMax() Else FindMinMax()
  344.             Invalidate()
  345.         End Set
  346.     End Property
  347.  
  348.     Private _OverrideMinValue As Single = 0.0F
  349.     Public Property OverrideMinValue() As Single
  350.         Get
  351.             Return _OverrideMinValue
  352.         End Get
  353.         Set(ByVal value As Single)
  354.             _OverrideMinValue = value
  355.             InvalidateMinMax()
  356.             Invalidate()
  357.         End Set
  358.     End Property
  359.  
  360.     Private _OverrideMax As Boolean = False
  361.     Public Property OverrideMax() As Boolean
  362.         Get
  363.             Return _OverrideMax
  364.         End Get
  365.         Set(ByVal value As Boolean)
  366.             _OverrideMax = value
  367.             If value Then InvalidateMinMax() Else FindMinMax()
  368.             Invalidate()
  369.         End Set
  370.     End Property
  371.  
  372.     Private _OverrideMaxValue As Single = 100.0F
  373.     Public Property OverrideMaxValue() As Single
  374.         Get
  375.             Return _OverrideMaxValue
  376.         End Get
  377.         Set(ByVal value As Single)
  378.             _OverrideMaxValue = value
  379.             InvalidateMinMax()
  380.             Invalidate()
  381.         End Set
  382.     End Property
  383.  
  384.     Private Sub InvalidateMinMax()
  385.         If _OverrideMin Then _MinimumValue = _OverrideMinValue
  386.         If _OverrideMax Then _MaximumValue = _OverrideMaxValue
  387.     End Sub
  388.  
  389.     Private SS As Size
  390.     Private SW, SH, SHH As Integer
  391.  
  392.     Private SG As Graphics
  393.  
  394.     Public Overrides Property Font As Font
  395.         Get
  396.             Return MyBase.Font
  397.         End Get
  398.         Set(value As Font)
  399.             MyBase.Font = value
  400.  
  401.             SS = SG.MeasureString("999K", Font).ToSize()
  402.             SW = SS.Width + 5
  403.             SH = SS.Height + 5
  404.             SHH = CInt(Math.Ceiling((SS.Height / 2) / 2) * 2)
  405.  
  406.             Invalidate()
  407.         End Set
  408.     End Property
  409.  
  410. #End Region
  411.  
  412. #Region " Graph Values "
  413.  
  414.     Private _MaximumValue As Single = Single.MinValue
  415.     Private _MinimumValue As Single = Single.MaxValue
  416.     Private CurrentValue As Single
  417.  
  418.     Private _Values As List(Of Single)
  419.     Private _SmoothValues As List(Of Single)
  420.  
  421.     Public Property Values() As Single()
  422.         Get
  423.             Return _Values.ToArray()
  424.         End Get
  425.         Set(ByVal value As Single())
  426.             Clear()
  427.  
  428.             AddValues(value)
  429.  
  430.             InvalidateSmoothValues()
  431.             FindMinMax()
  432.         End Set
  433.     End Property
  434.  
  435.     Public Sub AddValue(ByVal value As Single)
  436.         Index = -1
  437.         _Values.Add(value)
  438.  
  439.         CleanValues()
  440.  
  441.         InvalidateSmoothValues()
  442.         FindMinMax()
  443.  
  444.         Invalidate()
  445.     End Sub
  446.  
  447.     Public Sub AddValues(ByVal values As Single())
  448.         Index = -1
  449.         _Values.AddRange(values)
  450.  
  451.         CleanValues()
  452.  
  453.         InvalidateSmoothValues()
  454.         FindMinMax()
  455.  
  456.         Invalidate()
  457.     End Sub
  458.  
  459.     Private Sub InvalidateSmoothValues()
  460.         If Not _DataSmoothing Then Return
  461.  
  462.         _SmoothValues.Clear()
  463.  
  464.         Dim Mean As Single
  465.         Dim Min, Max As Integer
  466.  
  467.         For I As Integer = 0 To _Values.Count - 1
  468.             Mean = 0.0F
  469.  
  470.             Min = Math.Max(I - _DataSmoothingLevel, 0)
  471.             Max = Math.Min(I + _DataSmoothingLevel, _Values.Count - 1)
  472.  
  473.             For X As Integer = Min To Max
  474.                 Mean += _Values(X)
  475.             Next
  476.  
  477.             Mean = Mean / ((Max - Min) + 1)
  478.             _SmoothValues.Add(Mean)
  479.         Next
  480.     End Sub
  481.  
  482.     Private Sub FindMinMax()
  483.         _MaximumValue = Single.MinValue
  484.         _MinimumValue = Single.MaxValue
  485.  
  486.         For I As Integer = 0 To _Values.Count - 1
  487.  
  488.             If _DataSmoothing Then
  489.                 CurrentValue = _SmoothValues(I)
  490.             Else
  491.                 CurrentValue = _Values(I)
  492.             End If
  493.  
  494.             If (CurrentValue > _MaximumValue) Then _MaximumValue = CurrentValue
  495.             If (CurrentValue < _MinimumValue) Then _MinimumValue = CurrentValue
  496.         Next
  497.  
  498.         InvalidateMinMax()
  499.     End Sub
  500.  
  501.     Private Sub CleanValues()
  502.         If _Values.Count > Width Then
  503.             _Values.RemoveRange(0, _Values.Count - Width)
  504.         End If
  505.     End Sub
  506.  
  507.     Public Sub Clear()
  508.         _Values.Clear()
  509.         _SmoothValues.Clear()
  510.  
  511.         _MaximumValue = Single.MinValue
  512.         _MinimumValue = Single.MaxValue
  513.  
  514.         InvalidateMinMax()
  515.     End Sub
  516.  
  517. #End Region
  518.  
  519.     Private SB As String
  520.     Private FB1, FB2 As Single
  521.  
  522.     Private G As Graphics
  523.     Private GP As GraphicsPath
  524.  
  525.     Private P As Point
  526.     Private PS As PointF()
  527.     Private R1, R2, R3 As Rectangle
  528.  
  529.     Protected Overrides Sub OnPaint(e As PaintEventArgs)
  530.         G = e.Graphics
  531.         G.Clear(BackColor)
  532.  
  533.         R1 = New Rectangle(SW, 0, Width - SW, Height) 'Height - SH
  534.  
  535.         If Not _DrawDataColumn Then
  536.             R1.X = 0
  537.             R1.Width = Width
  538.         End If
  539.  
  540.         R2 = New Rectangle(R1.X + 10, R1.Y + 10, R1.Width - 20, R1.Height - 20)
  541.  
  542.         If Not _SidePadding Then
  543.             R2.X = R1.X
  544.             R2.Width = R1.Width
  545.         End If
  546.  
  547.         G.FillRectangle(_FillColor, R1)
  548.  
  549.         For I As Integer = 0 To 10
  550.             FB1 = R2.Y + CSng((R2.Height - 1) * (I * 0.1))
  551.  
  552.             If _DrawHorizontalLines Then
  553.                 G.DrawLine(_HorizontalLineColor, R1.X, FB1, R1.Right - 1, FB1)
  554.             End If
  555.  
  556.             If _DrawDataColumn AndAlso (_Values.Count > 1) Then
  557.                 If (I Mod 2 = 0) Then
  558.                     G.DrawLine(_BorderColor, R1.X - 4, FB1, R1.X, FB1)
  559.  
  560.                     CurrentValue = CInt(((_MaximumValue - _MinimumValue) * (1 - (I * 0.1))) + _MinimumValue)
  561.                     SB = SmallValue(CurrentValue)
  562.  
  563.                     SS = G.MeasureString(SB, Font).ToSize()
  564.                     G.DrawString(SB, Font, _DataColumnForeColor, R1.X - 5 - SS.Width, FB1 - SHH)
  565.                 End If
  566.             End If
  567.         Next
  568.  
  569.         If _Values.Count > 1 Then
  570.             PS = New PointF(_Values.Count + 1) {}
  571.             FB1 = CSng((R2.Width - 1) / (_Values.Count - 1))
  572.  
  573.             For I As Integer = 0 To _Values.Count - 1
  574.                 FB2 = R2.X + (I * FB1)
  575.  
  576.                 If _DataSmoothing Then
  577.                     CurrentValue = (_SmoothValues(I) - _MinimumValue) / Math.Max(_MaximumValue - _MinimumValue, 1)
  578.                 Else
  579.                     CurrentValue = (_Values(I) - _MinimumValue) / Math.Max(_MaximumValue - _MinimumValue, 1)
  580.                 End If
  581.  
  582.                 If CurrentValue > 1 Then
  583.                     CurrentValue = 1
  584.                 ElseIf CurrentValue < 0 Then
  585.                     CurrentValue = 0
  586.                 End If
  587.  
  588.                 PS(I) = New PointF(FB2, CInt(R2.Bottom - ((R2.Height - 1) * CurrentValue) - 1))
  589.  
  590.                 If _DrawVerticalLines Then
  591.                     G.DrawLine(_VerticalLineColor, FB2, R1.Y, FB2, R1.Bottom)
  592.                 End If
  593.             Next
  594.  
  595.             PS(PS.Length - 2) = New PointF(R2.Right - 1, R1.Bottom - 1)
  596.             PS(PS.Length - 1) = New PointF(R2.X, R1.Bottom - 1)
  597.  
  598.             G.SmoothingMode = SmoothingMode.HighQuality
  599.  
  600.             If _DrawLineGraph Then
  601.                 Array.Resize(PS, PS.Length - 2)
  602.                 G.DrawLines(_LineGraphColor, PS)
  603.             Else
  604.                 GP.AddPolygon(PS)
  605.                 GP.CloseFigure()
  606.  
  607.                 G.FillPath(_GraphFillColor, GP)
  608.                 G.DrawPath(_GraphBorderColor, GP)
  609.                 GP.Reset()
  610.             End If
  611.  
  612.             If _DrawHoverData AndAlso Not (Index < 0) Then
  613.                 G.SetClip(R1)
  614.  
  615.                 P = New Point(CInt(PS(Index).X), CInt(PS(Index).Y))
  616.                 R3 = New Rectangle(P.X - 4, P.Y - 4, 8, 8)
  617.  
  618.                 If _DrawHoverLine Then
  619.                     G.DrawLine(_HoverLineColor, P.X, R1.Y, P.X, R1.Bottom - 1)
  620.                 End If
  621.  
  622.                 G.FillEllipse(_HoverFillColor, R3)
  623.                 G.DrawEllipse(_HoverBorderColor, R3)
  624.  
  625.                 If _DataSmoothing Then
  626.                     SB = _SmoothValues(Index).ToString("N0")
  627.                 Else
  628.                     SB = _Values(Index).ToString("N0")
  629.                 End If
  630.  
  631.                 SS = G.MeasureString(SB, Font).ToSize()
  632.  
  633.                 P = PointToClient(MousePosition)
  634.  
  635.                 R3 = New Rectangle(P.X + 24, P.Y, SS.Width + 20, SS.Height + 10)
  636.                 If (R3.X + R3.Width) > (R1.Right - 1) Then R3.X = P.X - R3.Width - 16
  637.                 If (R3.Y + R3.Height) > (R1.Bottom - 1) Then R3.Y = R1.Bottom - R3.Height - 1
  638.  
  639.                 G.DrawRectangle(_HoverLabelShadowColor, R3)
  640.                 G.FillRectangle(_HoverLabelFillColor, R3)
  641.                 G.DrawRectangle(_HoverLabelBorderColor, R3)
  642.  
  643.                 G.DrawString(SB, Font, _HoverLabelForeColor, New Point(R3.X + 10, R3.Y + 5))
  644.             End If
  645.  
  646.             G.ResetClip()
  647.             G.SmoothingMode = SmoothingMode.None
  648.         End If
  649.  
  650.         G.DrawRectangle(_BorderColor, R1.X, R1.Y, R1.Width - 1, R1.Height - 1)
  651.     End Sub
  652.  
  653.     Private Function SmallValue(value As Single) As String
  654.         Dim R As Integer = CInt(value)
  655.  
  656.         Select Case R
  657.             Case Is >= 1000000000
  658.                 Return (R \ 1000000000) & "B"
  659.             Case Is >= 1000000
  660.                 Return (R \ 1000000) & "M"
  661.             Case Is >= 1000
  662.                 Return (R \ 1000) & "K"
  663.             Case Else
  664.                 Return CStr(R)
  665.         End Select
  666.     End Function
  667.  
  668. #Region " Hover Handler "
  669.  
  670.     Private Index As Integer = -1
  671.     Private LastMove As Date
  672.  
  673.     Protected Overrides Sub OnMouseMove(e As MouseEventArgs)
  674.         If Not _DrawHoverData Then Return
  675.  
  676.         R1 = New Rectangle(SW, 0, Width - SW, Height - SH)
  677.         R2 = New Rectangle(R1.X + 8, R1.Y + 8, R1.Width - 16, R1.Height - 16)
  678.  
  679.         FB1 = CSng((R2.Width - 1) / (_Values.Count - 1))
  680.  
  681.         If R1.Contains(e.Location) Then
  682.             Index = CInt((e.X - R2.X) / FB1)
  683.             If Not Index < _Values.Count Then Index = -1
  684.         Else
  685.             Index = -1
  686.         End If
  687.  
  688.         If Date.Now > LastMove.AddMilliseconds(33) Then
  689.             LastMove = Date.Now
  690.             Invalidate()
  691.         End If
  692.     End Sub
  693.  
  694.     Protected Overrides Sub OnMouseLeave(e As EventArgs)
  695.         If Not _DrawHoverData Then Return
  696.  
  697.         Index = -1
  698.         Invalidate()
  699.     End Sub
  700.  
  701. #End Region
  702.  
  703. End Class
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement