Option Strict On Imports System.Drawing.Drawing2D Public Class PhotoSlider Inherits Control '########## Credits ######### '# GDI PhotoSlider # '# Created by: Blink # '# Released on: 27 dec 2012 # '############################ 'You can contact me at: 'http://www.hackforums.net/member.php?action=profile&uid=551863 #Region "Properties" Public Property Images As ImageList Private _intArrowSize As Integer = 10 Public Property ArrowSize As Integer Get Return _intArrowSize End Get Set(ByVal value As Integer) _intArrowSize = value Invalidate() End Set End Property Private _intHoverOutset As Integer = 10 Public Property HoverOutset As Integer Get Return _intHoverOutset End Get Set(ByVal value As Integer) _intHoverOutset = value Invalidate() End Set End Property Private _intOverlap As Integer = 5 Public Property Overlap As Integer Get Return _intOverlap End Get Set(ByVal value As Integer) _intOverlap = value Invalidate() End Set End Property Private _intFocused As Integer = 0 Public Property FocusedIndex As Integer Get Return _intFocused End Get Set(ByVal value As Integer) _intFocused = value Invalidate() End Set End Property Private _blnDrawOutline As Boolean = True Public Property DrawOutline As Boolean Get Return _blnDrawOutline End Get Set(ByVal value As Boolean) _blnDrawOutline = value Invalidate() End Set End Property #End Region Sub New() Size = New Size(600, 150) DoubleBuffered = True End Sub Public Sub MoveForward() If FocusedIndex + 1 > Images.Images.Count - 1 Then FocusedIndex = 0 Else FocusedIndex += 1 End If End Sub Public Sub MoveBackward() If FocusedIndex - 1 < 0 Then FocusedIndex = Images.Images.Count - 1 Else FocusedIndex -= 1 End If End Sub 'Gets index relative to the focused index Private Function GetIndex(ByVal intOff As Integer) As Integer If FocusedIndex + intOff = Images.Images.Count Then Return 0 ElseIf FocusedIndex + intOff = Images.Images.Count + 1 Then Return 1 ElseIf FocusedIndex + intOff = -1 Then Return Images.Images.Count - 1 ElseIf FocusedIndex + intOff = -2 Then Return Images.Images.Count - 2 Else Return FocusedIndex + intOff End If End Function Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs) Dim G As Graphics = e.Graphics 'Order is important for Overlap For i As Integer = -2 To 0 If i <> HoveredIndex Then DrawPicture(G, i) End If If i <> Math.Abs(i) And Math.Abs(i) <> HoveredIndex Then DrawPicture(G, Math.Abs(i)) End If Next 'Draw hovered last for Overlap If HoveredIndex <> -3 Then DrawPicture(G, HoveredIndex) End If DrawArrow(G, 0) 'Left DrawArrow(G, 1) 'Right MyBase.OnPaint(e) End Sub Sub DrawArrow(ByVal G As Graphics, ByVal intArrowIndex As Integer) Dim rctBounds As Rectangle = GetArrowBounds(intArrowIndex) Dim intHalf As Integer = CInt(ArrowSize / 2) Dim intAlfa As Integer If intArrowIndex = HoveredArrow And blnMouseIsDown Then intAlfa = 255 ElseIf intArrowIndex = HoveredArrow Then intAlfa = 200 Else intAlfa = 150 End If G.SmoothingMode = SmoothingMode.AntiAlias Select Case intArrowIndex Case 0 'Left Dim gpLeftArrow As New GraphicsPath gpLeftArrow.AddLine(rctBounds.X + intHalf, rctBounds.Y + 0, rctBounds.X + ArrowSize, rctBounds.Y + 0) gpLeftArrow.AddLine(rctBounds.X + ArrowSize, rctBounds.Y + 0, rctBounds.X + intHalf, rctBounds.Y + intHalf) gpLeftArrow.AddLine(rctBounds.X + intHalf, rctBounds.Y + intHalf, rctBounds.X + ArrowSize, rctBounds.Y + ArrowSize) gpLeftArrow.AddLine(rctBounds.X + ArrowSize, rctBounds.Y + ArrowSize, rctBounds.X + intHalf, rctBounds.Y + ArrowSize) gpLeftArrow.AddLine(rctBounds.X + intHalf, rctBounds.Y + ArrowSize, rctBounds.X + 0, rctBounds.Y + intHalf) gpLeftArrow.AddLine(rctBounds.X + 0, rctBounds.Y + intHalf, rctBounds.X + intHalf, rctBounds.Y + 0) G.FillPath(New SolidBrush(Color.FromArgb(intAlfa, 75, 75, 75)), gpLeftArrow) Case 1 'Right Dim gpRightArrow As New GraphicsPath gpRightArrow.AddLine(rctBounds.X + 0, rctBounds.Y + 0, rctBounds.X + intHalf, rctBounds.Y + 0) gpRightArrow.AddLine(rctBounds.X + intHalf, rctBounds.Y + 0, rctBounds.X + ArrowSize, rctBounds.Y + intHalf) gpRightArrow.AddLine(rctBounds.X + ArrowSize, rctBounds.Y + intHalf, rctBounds.X + intHalf, rctBounds.Y + ArrowSize) gpRightArrow.AddLine(rctBounds.X + intHalf, rctBounds.Y + ArrowSize, rctBounds.X + 0, rctBounds.Y + ArrowSize) gpRightArrow.AddLine(rctBounds.X + 0, rctBounds.Y + ArrowSize, rctBounds.X + intHalf, rctBounds.Y + intHalf) gpRightArrow.AddLine(rctBounds.X + intHalf, rctBounds.Y + intHalf, rctBounds.X + 0, rctBounds.Y + 0) G.FillPath(New SolidBrush(Color.FromArgb(intAlfa, 75, 75, 75)), gpRightArrow) End Select End Sub Sub DrawPicture(ByVal G As Graphics, ByVal index As Integer) G.FillRectangle(Brushes.White, GetPictureBounds(index)) Try G.DrawImage(Images.Images(GetIndex(index)), GetPictureBounds(index)) Catch ex As Exception G.FillRectangle(Brushes.CornflowerBlue, GetPictureBounds(index)) End Try If DrawOutline Then G.DrawRectangle(Pens.Black, GetPictureBounds(index)) End Sub 'Returns the bounds of the requested index, inclusive the hover Private Function GetPictureBounds(ByVal Index As Integer) As Rectangle If Not Index = HoveredIndex Then Return GetNormalPictureBounds(Index) Else Dim rctNormal As Rectangle = GetNormalPictureBounds(Index) Return New Rectangle(rctNormal.X - HoverOutset, rctNormal.Y - HoverOutset, rctNormal.Width + 2 * HoverOutset, rctNormal.Height + 2 * HoverOutset) End If End Function 'Returns the bounds of the requested index, exclusive the hover Private Function GetNormalPictureBounds(ByVal Index As Integer) As Rectangle Select Case Index Case -2 Dim rctNext As Rectangle = GetNormalPictureBounds(Index + 1) Return New Rectangle(rctNext.X + (Overlap * 3) - rctNext.Width, rctNext.Y + Overlap, rctNext.Width - Overlap * 2, rctNext.Height - 2 * Overlap) Case -1 Dim rctNext As Rectangle = GetNormalPictureBounds(Index + 1) Return New Rectangle(rctNext.X + (Overlap * 3) - rctNext.Width, rctNext.Y + Overlap, rctNext.Width - Overlap * 2, rctNext.Height - 2 * Overlap) Case 0 Return New Rectangle(CInt(Width / 2) - CInt((Height - ArrowSize) / 2 - HoverOutset), HoverOutset, (Height - ArrowSize) - HoverOutset * 2, (Height - ArrowSize) - HoverOutset * 2 - 1) Case 1 Dim rctPrevious As Rectangle = GetNormalPictureBounds(Index - 1) Return New Rectangle(rctPrevious.X + rctPrevious.Width - Overlap, rctPrevious.Y + Overlap, rctPrevious.Width - Overlap * 2, rctPrevious.Height - Overlap * 2) Case 2 Dim rctPrevious As Rectangle = GetNormalPictureBounds(Index - 1) Return New Rectangle(rctPrevious.X + rctPrevious.Width - Overlap, rctPrevious.Y + Overlap, rctPrevious.Width - Overlap * 2, rctPrevious.Height - Overlap * 2) End Select End Function Private HoveredIndex As Integer = -3 Private HoveredArrow As Integer = -1 Protected Overrides Sub OnMouseMove(ByVal e As System.Windows.Forms.MouseEventArgs) Dim intNewHovered As Integer = GetHoveredIndex(e.Location) If intNewHovered <> HoveredIndex Then HoveredIndex = intNewHovered Invalidate() End If Dim intNewHoveredArrow As Integer = GetHoveredArrowIndex(e.Location) If intNewHoveredArrow <> HoveredArrow Then HoveredArrow = intNewHoveredArrow Invalidate() End If MyBase.OnMouseMove(e) End Sub Protected Overrides Sub OnMouseLeave(ByVal e As System.EventArgs) HoveredIndex = -3 Invalidate() MyBase.OnMouseLeave(e) End Sub Private blnMouseIsDown As Boolean = False Protected Overrides Sub OnMouseDown(ByVal e As System.Windows.Forms.MouseEventArgs) blnMouseIsDown = True Invalidate() MyBase.OnMouseDown(e) End Sub Protected Overrides Sub OnMouseUp(ByVal e As System.Windows.Forms.MouseEventArgs) blnMouseIsDown = False Dim intIndex As Integer = GetHoveredIndex(e.Location) If intIndex <> -3 Then FocusedIndex = GetIndex(intIndex) End If Dim intArrow As Integer = GetHoveredArrowIndex(e.Location) If intArrow = 0 Then MoveBackward() ElseIf intArrow = 1 Then MoveForward() End If MyBase.OnMouseUp(e) End Sub Private Function GetHoveredIndex(ByVal pntLoc As Point) As Integer For i As Integer = 0 To -2 Step -1 If GetPictureBounds(i).Contains(pntLoc) Then Return i ElseIf GetPictureBounds(Math.Abs(i)).Contains(pntLoc) Then Return Math.Abs(i) End If Next Return -3 End Function Private Function GetArrowBounds(ByVal intIndex As Integer) As Rectangle Select Case intIndex Case 0 'Left Return New Rectangle(CInt(Width / 2) - ArrowSize - 1, Height - 1 - ArrowSize, ArrowSize, ArrowSize) Case 1 'Right Return New Rectangle(CInt(Width / 2) + 1, Height - 1 - ArrowSize, ArrowSize, ArrowSize) End Select End Function Private Function GetHoveredArrowIndex(ByVal pntLoc As Point) As Integer For i As Integer = 0 To 1 If GetArrowBounds(i).Contains(pntLoc) Then Return i End If Next Return -1 End Function End Class