-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCustomTooltip.vb
More file actions
144 lines (114 loc) · 5.39 KB
/
CustomTooltip.vb
File metadata and controls
144 lines (114 loc) · 5.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
Public Class CustomToolTip
Inherits ToolTip
Public font As Font
Public text As String
Public lines As Integer = 1
Public currentowner As ToolStripDropDown
Public currentitem As ToolStripItem
Public Sub New()
MyBase.New()
Me.OwnerDraw = True
Me.ShowAlways = True
AddHandler Me.Popup, AddressOf Me.OnPopup
AddHandler Me.Draw, AddressOf Me.OnDraw
End Sub
Dim delaysw As Stopwatch = Stopwatch.StartNew
Public Shadows Sub Hide()
If currentowner IsNot Nothing Then MyBase.Hide(currentowner)
End Sub
Public Sub ShowToolTip(item As ToolStripItem)
Me.Hide()
Dim tsdd As ToolStripDropDown = item.GetCurrentParent
If tsdd Is Nothing OrElse String.IsNullOrEmpty(item.ToolTipText) Then
delaysw.Restart()
Exit Sub
End If
If delaysw.ElapsedMilliseconds < 250 Then
Exit Sub
End If
delaysw.Restart()
currentowner = tsdd ' remember the control
currentitem = item
Dim offset = New Point(5, 5)
' Use the drop-down font
Me.font = tsdd.Font
Me.text = item.ToolTipText
Me.lines = text.Count(Function(c) c = vbCr) + 1
' Get menu bounds in screen coordinates
Dim menuBounds As Rectangle = tsdd.Bounds
Dim screenArea As Rectangle = Screen.FromControl(tsdd).WorkingArea
Dim screenBounds As Rectangle = Screen.FromControl(tsdd).Bounds
' Estimate tooltip size (can be adjusted later or made dynamic)
If String.IsNullOrEmpty(text) Then
Exit Sub
End If
' Measure the width of each line
Dim maxWidth As Integer = 0
Using g As Graphics = Graphics.FromHwnd(IntPtr.Zero)
For Each line As String In text.Split({vbCrLf, vbLf}, StringSplitOptions.None)
Dim size As SizeF = g.MeasureString(line, Me.font)
If size.Width > maxWidth Then maxWidth = CInt(Math.Ceiling(size.Width))
Next
End Using
Dim tooltipWidth As Integer = maxWidth + 10
Dim tooltipHeight As Integer = (12 + 6 * lines) * scaling
' Start positioning to the right and below the menu
Dim tooltipX As Integer = menuBounds.Right + offset.X
Dim tooltipY As Integer = menuBounds.Top + offset.Y
' Adjust if going off the right edge
If tooltipX + tooltipWidth > screenArea.Right Then
tooltipX = menuBounds.Left - tooltipWidth - offset.X
End If
' Adjust if going off bottom edge
If tooltipY + tooltipHeight > screenArea.Bottom Then
tooltipY = menuBounds.Bottom - tooltipHeight - offset.Y
End If
' Adjust if going above top
If tooltipY < screenArea.Top Then
tooltipY = screenArea.Top + offset.Y
End If
' Adjust for taskbar on top
If screenArea.Top > screenBounds.Top Then
tooltipY += screenArea.Top - screenBounds.Top
End If
' Adjust for taskbar on right
If screenArea.Right < screenBounds.Right Then
tooltipX -= screenBounds.Right - screenArea.Right
End If
Dim pt = tsdd.PointToClient(New Point(tooltipX, tooltipY))
' Show tooltip at computed absolute position
Me.Show(text, tsdd, pt.X, pt.Y)
End Sub
Private Sub OnPopup(ByVal sender As Object, ByVal e As PopupEventArgs)
If String.IsNullOrEmpty(text) Then
e.ToolTipSize = New Size(0, 0)
e.Cancel = True
Exit Sub
End If
' Measure the width of each line
Dim maxWidth As Integer = 0
Using g As Graphics = Graphics.FromHwnd(e.AssociatedWindow.Handle)
For Each line As String In text.Split({vbCrLf, vbLf}, StringSplitOptions.RemoveEmptyEntries)
Dim size As SizeF = g.MeasureString(line, Me.font)
If size.Width > maxWidth Then maxWidth = CInt(Math.Ceiling(size.Width))
Next
End Using
e.ToolTipSize = New Size(maxWidth + 10, (12 + 8 * lines) * scaling)
End Sub
Private Sub OnDraw(ByVal sender As Object, ByVal e As DrawToolTipEventArgs)
Using g As Graphics = e.Graphics
Using b As New Drawing2D.LinearGradientBrush(e.Bounds, Color.FromArgb(255, 60, 60, 60), Color.Black, 0.0F)
g.FillRectangle(b, e.Bounds)
End Using
g.DrawRectangle(New Pen(Brushes.Red, 1), New Rectangle(e.Bounds.X, e.Bounds.Y, e.Bounds.Width - 1, e.Bounds.Height - 1))
Using bloombrush As New SolidBrush(Color.FromArgb(60, Color.HotPink))
Dim sf As Integer = 1 * scaling
g.DrawString(e.ToolTipText, Me.font, bloombrush, New PointF(e.Bounds.X + 5 - sf, e.Bounds.Y + 5 * scaling)) ' shadow layer
g.DrawString(e.ToolTipText, Me.font, bloombrush, New PointF(e.Bounds.X + 5 + sf, e.Bounds.Y + 5 * scaling)) ' shadow layer
g.DrawString(e.ToolTipText, Me.font, bloombrush, New PointF(e.Bounds.X + 5, e.Bounds.Y + 5 * scaling - sf)) ' shadow layer
g.DrawString(e.ToolTipText, Me.font, bloombrush, New PointF(e.Bounds.X + 5, e.Bounds.Y + 5 * scaling + sf)) ' shadow layer
End Using
g.DrawString(e.ToolTipText, Me.font, If(currentitem.Enabled, Brushes.White, Brushes.DarkGray), New PointF(e.Bounds.X + 5, e.Bounds.Y + 5 * scaling)) ' top layer
End Using
End Sub
End Class