none
Need help on creating timeline of a music player program RRS feed

  • Question

  • I'm working on a Music Player program (using PlayerControl : Interop.WMPLib.dll) with an extra feature :

    By pressing buttons with different colors, user can put some reminder points on player's timeline. Thus, each reminder point's color is corresponded to the color of its creator button. (Small circular shapes are good choice to be as reminder points)


    This is my approach:

    The timeline is actually a trackbar that shows the current position with its thumb.

    The timeline's length and maximum values are fixed ; 1200 and 100.

    With the code below, the trackbar value is calculated :

    Dim CPos As Integer = Convert.ToInt32(PlayerControl.Ctlcontrols.currentPosition * 1000)
            Dim DurationValue As Integer = Convert.ToInt32(PlayerControl.currentMedia.duration * 1000)
            If DurationValue > 0 Then
                TrackBar.Value = Convert.ToInt32((CPos * 100) / DurationValue)
            End If

    With the help of

    PlayerControl.Ctlcontrols.currentPosition

    it is possible to specify where each created reminder point should be placed on the timeline.


    Here is a picture of what I've done and what I'm looking for :



    The pink rectangular area is the main question to this thread:

    The reminder points should be placed in this area (above the trackbar). For example, if half of the music is played and user presses the red button, a red point (like the ones in the picture) should be placed on the middle of the timeline in the pink rectangular area.

    What's your approach ? 

    There might be a few issues you might consider as I'm thinking of right now:

    1- Is it a good idea to use a trackbar as the main framework of the timeline at all ? If not, what are the alternatives that are better to use than using a trackbar?

    2- (using a trackbar) What happens when user once play a music completely to its end and put some reminders on the time line, then he plays it another time, and by chance, some new reminders might be in the same location of previous reminders but with different colors. Reminder points should not be placed on the previous reminders if there is any , but, I guess it is a better idea to put each new reminder point above the previous reminder points (though there might me another issue : more reminders, more vertical space needed above the timeline!)

    3- (using a trackbar) How to provide the trackbar's lines (white ones in the picture) with labels showing their corresponding time in seconds ? It is not possible to show each line's time because the trackbar's length is fixed and  there would be lack of space for greater numbers ...

    4- ... ?

    Thanks in advance.





    • Edited by Kevin993 Monday, April 22, 2019 8:23 AM
    Monday, April 22, 2019 8:21 AM

Answers

  • This is the famous picturebox inside a picturebox method of scrolling.

    Since your data is static ie you have a song with a fixed time length this approach is easy.

    With this method the timeline is drawn full length on a picturebox width that is inside a second parent or outside picturebox. Then the inside picturebox is moved directly with the scrollbar.

    The inside pic is 3 x the outside then you can scroll from end to end with one scrollbar range. The scroll bar range is 0 to 100 and then ratio that to the innerpic width.

    To draw a seconds grid just spread the TimeMax across the width of the inside pic. Timemax is the length of the song in sec. So the grid is from 0 to timemax across the width of the picturebox.

    One can work on something like this endlessly this is just a start.

    :)

    The example makes the controls just cut and paste into an empty form, change the form name as reqd.

     

    Public Class Form5
        Private WithEvents OutsidePic As New PictureBox With {.Parent = Me, .BorderStyle = BorderStyle.FixedSingle}
        Private WithEvents InsidePic As New PictureBox With {.Parent = OutsidePic, .BorderStyle = BorderStyle.FixedSingle}
        Private WithEvents HScroll1 As New HScrollBar With {.Parent = OutsidePic, .Maximum = 100,
            .Minimum = 0, .SmallChange = 1, .Dock = DockStyle.Bottom}
        Private Border As Integer = 20
        Private InnerHeight As Integer = 200
        Private TimeMax As Integer = 240 'seconds
        Private ScaleRatio As Double = 1
        Private pts As New List(Of Integer)
        '
        Private Sub Form5_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            ClientSize = New Size(500, 300)
            BackColor = Color.DimGray
            OutsidePic.BackColor = Color.Black
            InsidePic.BackColor = Color.White
            OutsidePic.Location = New Point(Border, Border)
            TimeMax = 240  'this is the length of this song in seconds
            pts.Add(30)
            pts.Add(67)
            pts.Add(122)
            HScroll1.Value = 0
            HScroll1.BringToFront()
    
            Form5_Resize(0, Nothing)
        End Sub
    
        Private Sub Form5_Resize(sender As Object, e As EventArgs) Handles Me.Resize
    
            OutsidePic.ClientSize = New Size(ClientSize.Width - (2 * Border), InnerHeight)
    
            'set inside width to show the time max on the current window size
            Dim w As Integer = CInt(3 * OutsidePic.ClientSize.Width)
            If w < 10 Then w=10
    
            InsidePic.ClientSize = New Size(w, InnerHeight)
    
            InsidePic.Invalidate()
        End Sub
    
        Private Sub InsidePic_Paint(sender As Object, e As PaintEventArgs) Handles InsidePic.Paint
            Dim xStep As Integer
    
            Select Case TimeMax
                Case < 50
                    xStep = 2
                Case < 100
                    xStep = 5
                Case < 100
                    xStep = 10
                Case < 500
                    xStep = 20
                Case Else
                    xStep = 50
            End Select
    
            Dim sr As Single = CSng(ScaleRatio * InsidePic.ClientSize.Width / TimeMax)
            Dim yMax As Integer = InsidePic.Height
    
            With e.Graphics
                .ScaleTransform(sr, sr)
    
                Using p As New Pen(Color.SkyBlue, CSng(sr / 100)),
                        p2 As New Pen(Color.Lime, CSng(sr / 50)),
                        p3 As New Pen(Color.Red, CSng(sr / 10)),
                        br As New SolidBrush(Color.LightGray),
                        f As New Font("tahoma", CSng(10 / sr), FontStyle.Bold)
    
                    For x As Single = 0 To TimeMax Step xStep
                        .DrawLine(p, x, 0, x, yMax)
                        .DrawString(x.ToString, f, br, x, 0)
                    Next
    
                    Dim y As Single = CSng(0.5 * InsidePic.ClientSize.Height / sr)
    
                    .DrawLine(p2, 0, y, TimeMax, y)
                    .DrawString(" Seconds", f, br, 0, f.Height)
    
                    For Each x As Integer In pts
                        .DrawEllipse(p3, New RectangleF(x, CSng(0.7 * y), CSng(6 / sr), CSng(6 / sr)))
                    Next
                End Using
            End With
        End Sub
    
        Private Sub HScroll1_ValueChanged(sender As Object, e As EventArgs) Handles HScroll1.ValueChanged
            Dim dx As Integer = CInt(1.1 * OutsidePic.ClientSize.Width - InsidePic.ClientSize.Width)
            InsidePic.Location = New Point(CInt(HScroll1.Value * dx / 100), 0)
        End Sub
    
        Private Sub Form5_MouseWheel(sender As Object, e As MouseEventArgs) Handles Me.MouseWheel
            ScaleRatio += Math.Sign(e.Delta) * 0.1
            If ScaleRatio > 5 Then ScaleRatio = 5
            If ScaleRatio < 0.1 Then ScaleRatio = 0.1
            InsidePic.Invalidate()
        End Sub
    End Class

    • Proposed as answer by Alex Li-MSFT Friday, April 26, 2019 6:41 AM
    • Marked as answer by Kevin993 Friday, April 26, 2019 10:08 AM
    Monday, April 22, 2019 6:36 PM

All replies

  • Is this a fixed size loop that you repeat? ie 2 minutes long repeated? Or is the length of the time and data scale dynamic and or always accumulating ie from 11.02 am EDT to now 12.33?

    See what I mean? In one case the data is a fixed size and therefore the tackbar fixed size can be scrolled somehow.

    In the other the size is changing so the trackbar scale has to change... somehow.

    You have to use a trackbar or scrollbar or something? You could draw your own but still has to be something. Is it fixed length or dynamic?

    Here is something we did using chart control to draw a time line. It has scrollbars and can zoom in and out. It uses a fixed length of time/data. I have also drawn my own versions that got very complex with cut/paste copy etc like a video/sound editor adobe premiere etc. So definitely can be done. :)

    https://social.msdn.microsoft.com/Forums/vstudio/en-US/ccff6fd9-3b36-4aa2-a9d4-ba3a56bae88f/how-to-draw-a-wav-chart-graph-with-real-time-postion-indicator?forum=vbgeneral

    Hmmm. It gets complicated. Has to be thought about worked on, studied. Depends on exactly what you want to do.

    Do you want to zoom in and out? The scroll bar must adjust for that. Then your time line becomes infinite basically so how do you set infinite on a scrollbar?

    How much development time do you want to spend on it? Practice drawing a grid with numbers there are many examples. Making the numbers fit the space is PHD/patent type stuff and not easy.

    First try to figure out what you are going to draw. Get something working, then label it. Add to it. Play with it. Use it. Fix it.

    Monday, April 22, 2019 10:27 AM
  • Is this a fixed size loop that you repeat? ie 2 minutes long repeated? Or is the length of the time and data scale dynamic and or always accumulating ie from 11.02 am EDT to now 12.33?

    See what I mean? In one case the data is a fixed size and therefore the tackbar fixed size can be scrolled somehow.

    In the other the size is changing so the trackbar scale has to change... somehow.

    You have to use a trackbar or scrollbar or something? You could draw your own but still has to be something. Is it fixed length or dynamic?

    Here is something we did using chart control to draw a time line. It has scrollbars and can zoom in and out. It uses a fixed length of time/data. I have also drawn my own versions that got very complex with cut/paste copy etc like a video/sound editor adobe premiere etc. So definitely can be done. :)

    https://social.msdn.microsoft.com/Forums/vstudio/en-US/ccff6fd9-3b36-4aa2-a9d4-ba3a56bae88f/how-to-draw-a-wav-chart-graph-with-real-time-postion-indicator?forum=vbgeneral

    Hmmm. It gets complicated. Has to be thought about worked on, studied. Depends on exactly what you want to do.

    Do you want to zoom in and out? The scroll bar must adjust for that. Then your time line becomes infinite basically so how do you set infinite on a scrollbar?

    How much development time do you want to spend on it? Practice drawing a grid with numbers there are many examples. Making the numbers fit the space is PHD/patent type stuff and not easy.

    First try to figure out what you are going to draw. Get something working, then label it. Add to it. Play with it. Use it. Fix it.


    It isn't a fixed size loop. As each music duration is different, it can not be limited to a fixed size loop. But It is possible to define a limitation as maximum duration of like 4 minutes.

    * The track bar width is fixed to 1200

    * No zoom in/out feature needed by now. I want to make it as much simple as possible. The only duty of this timeline is to show reminder points created at different current positions based on the trackbar. I want to help user know how far or near each reminder point is to another on the trackbar

    I know it might get really complicated creating timelines ... I would appreciate your suggestions and at least I can take a look at them to lean more.

    By the way, I check the link you provided me with asap.




    • Edited by Kevin993 Monday, April 22, 2019 12:26 PM
    Monday, April 22, 2019 12:23 PM
  • This is the famous picturebox inside a picturebox method of scrolling.

    Since your data is static ie you have a song with a fixed time length this approach is easy.

    With this method the timeline is drawn full length on a picturebox width that is inside a second parent or outside picturebox. Then the inside picturebox is moved directly with the scrollbar.

    The inside pic is 3 x the outside then you can scroll from end to end with one scrollbar range. The scroll bar range is 0 to 100 and then ratio that to the innerpic width.

    To draw a seconds grid just spread the TimeMax across the width of the inside pic. Timemax is the length of the song in sec. So the grid is from 0 to timemax across the width of the picturebox.

    One can work on something like this endlessly this is just a start.

    :)

    The example makes the controls just cut and paste into an empty form, change the form name as reqd.

     

    Public Class Form5
        Private WithEvents OutsidePic As New PictureBox With {.Parent = Me, .BorderStyle = BorderStyle.FixedSingle}
        Private WithEvents InsidePic As New PictureBox With {.Parent = OutsidePic, .BorderStyle = BorderStyle.FixedSingle}
        Private WithEvents HScroll1 As New HScrollBar With {.Parent = OutsidePic, .Maximum = 100,
            .Minimum = 0, .SmallChange = 1, .Dock = DockStyle.Bottom}
        Private Border As Integer = 20
        Private InnerHeight As Integer = 200
        Private TimeMax As Integer = 240 'seconds
        Private ScaleRatio As Double = 1
        Private pts As New List(Of Integer)
        '
        Private Sub Form5_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            ClientSize = New Size(500, 300)
            BackColor = Color.DimGray
            OutsidePic.BackColor = Color.Black
            InsidePic.BackColor = Color.White
            OutsidePic.Location = New Point(Border, Border)
            TimeMax = 240  'this is the length of this song in seconds
            pts.Add(30)
            pts.Add(67)
            pts.Add(122)
            HScroll1.Value = 0
            HScroll1.BringToFront()
    
            Form5_Resize(0, Nothing)
        End Sub
    
        Private Sub Form5_Resize(sender As Object, e As EventArgs) Handles Me.Resize
    
            OutsidePic.ClientSize = New Size(ClientSize.Width - (2 * Border), InnerHeight)
    
            'set inside width to show the time max on the current window size
            Dim w As Integer = CInt(3 * OutsidePic.ClientSize.Width)
            If w < 10 Then w=10
    
            InsidePic.ClientSize = New Size(w, InnerHeight)
    
            InsidePic.Invalidate()
        End Sub
    
        Private Sub InsidePic_Paint(sender As Object, e As PaintEventArgs) Handles InsidePic.Paint
            Dim xStep As Integer
    
            Select Case TimeMax
                Case < 50
                    xStep = 2
                Case < 100
                    xStep = 5
                Case < 100
                    xStep = 10
                Case < 500
                    xStep = 20
                Case Else
                    xStep = 50
            End Select
    
            Dim sr As Single = CSng(ScaleRatio * InsidePic.ClientSize.Width / TimeMax)
            Dim yMax As Integer = InsidePic.Height
    
            With e.Graphics
                .ScaleTransform(sr, sr)
    
                Using p As New Pen(Color.SkyBlue, CSng(sr / 100)),
                        p2 As New Pen(Color.Lime, CSng(sr / 50)),
                        p3 As New Pen(Color.Red, CSng(sr / 10)),
                        br As New SolidBrush(Color.LightGray),
                        f As New Font("tahoma", CSng(10 / sr), FontStyle.Bold)
    
                    For x As Single = 0 To TimeMax Step xStep
                        .DrawLine(p, x, 0, x, yMax)
                        .DrawString(x.ToString, f, br, x, 0)
                    Next
    
                    Dim y As Single = CSng(0.5 * InsidePic.ClientSize.Height / sr)
    
                    .DrawLine(p2, 0, y, TimeMax, y)
                    .DrawString(" Seconds", f, br, 0, f.Height)
    
                    For Each x As Integer In pts
                        .DrawEllipse(p3, New RectangleF(x, CSng(0.7 * y), CSng(6 / sr), CSng(6 / sr)))
                    Next
                End Using
            End With
        End Sub
    
        Private Sub HScroll1_ValueChanged(sender As Object, e As EventArgs) Handles HScroll1.ValueChanged
            Dim dx As Integer = CInt(1.1 * OutsidePic.ClientSize.Width - InsidePic.ClientSize.Width)
            InsidePic.Location = New Point(CInt(HScroll1.Value * dx / 100), 0)
        End Sub
    
        Private Sub Form5_MouseWheel(sender As Object, e As MouseEventArgs) Handles Me.MouseWheel
            ScaleRatio += Math.Sign(e.Delta) * 0.1
            If ScaleRatio > 5 Then ScaleRatio = 5
            If ScaleRatio < 0.1 Then ScaleRatio = 0.1
            InsidePic.Invalidate()
        End Sub
    End Class

    • Proposed as answer by Alex Li-MSFT Friday, April 26, 2019 6:41 AM
    • Marked as answer by Kevin993 Friday, April 26, 2019 10:08 AM
    Monday, April 22, 2019 6:36 PM
  • This is the famous picturebox inside a picturebox method of scrolling.

    Since your data is static ie you have a song with a fixed time length this approach is easy.

    With this method the timeline is drawn full length on a picturebox width that is inside a second parent or outside picturebox. Then the inside picturebox is moved directly with the scrollbar.

    The inside pic is 3 x the outside then you can scroll from end to end with one scrollbar range. The scroll bar range is 0 to 100 and then ratio that to the innerpic width.

    To draw a seconds grid just spread the TimeMax across the width of the inside pic. Timemax is the length of the song in sec. So the grid is from 0 to timemax across the width of the picturebox.

    One can work on something like this endlessly this is just a start.

    :)

    The example makes the controls just cut and paste into an empty form, change the form name as reqd.

     

    Public Class Form5
        Private WithEvents OutsidePic As New PictureBox With {.Parent = Me, .BorderStyle = BorderStyle.FixedSingle}
        Private WithEvents InsidePic As New PictureBox With {.Parent = OutsidePic, .BorderStyle = BorderStyle.FixedSingle}
        Private WithEvents HScroll1 As New HScrollBar With {.Parent = OutsidePic, .Maximum = 100,
            .Minimum = 0, .SmallChange = 1, .Dock = DockStyle.Bottom}
        Private Border As Integer = 20
        Private InnerHeight As Integer = 200
        Private TimeMax As Integer = 240 'seconds
        Private ScaleRatio As Double = 1
        Private pts As New List(Of Integer)
        '
        Private Sub Form5_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            ClientSize = New Size(500, 300)
            BackColor = Color.DimGray
            OutsidePic.BackColor = Color.Black
            InsidePic.BackColor = Color.White
            OutsidePic.Location = New Point(Border, Border)
            TimeMax = 240  'this is the length of this song in seconds
            pts.Add(30)
            pts.Add(67)
            pts.Add(122)
            HScroll1.Value = 0
            HScroll1.BringToFront()
    
            Form5_Resize(0, Nothing)
        End Sub
    
        Private Sub Form5_Resize(sender As Object, e As EventArgs) Handles Me.Resize
    
            OutsidePic.ClientSize = New Size(ClientSize.Width - (2 * Border), InnerHeight)
    
            'set inside width to show the time max on the current window size
            Dim w As Integer = CInt(3 * OutsidePic.ClientSize.Width)
            If w < 10 Then w=10
    
            InsidePic.ClientSize = New Size(w, InnerHeight)
    
            InsidePic.Invalidate()
        End Sub
    
        Private Sub InsidePic_Paint(sender As Object, e As PaintEventArgs) Handles InsidePic.Paint
            Dim xStep As Integer
    
            Select Case TimeMax
                Case < 50
                    xStep = 2
                Case < 100
                    xStep = 5
                Case < 100
                    xStep = 10
                Case < 500
                    xStep = 20
                Case Else
                    xStep = 50
            End Select
    
            Dim sr As Single = CSng(ScaleRatio * InsidePic.ClientSize.Width / TimeMax)
            Dim yMax As Integer = InsidePic.Height
    
            With e.Graphics
                .ScaleTransform(sr, sr)
    
                Using p As New Pen(Color.SkyBlue, CSng(sr / 100)),
                        p2 As New Pen(Color.Lime, CSng(sr / 50)),
                        p3 As New Pen(Color.Red, CSng(sr / 10)),
                        br As New SolidBrush(Color.LightGray),
                        f As New Font("tahoma", CSng(10 / sr), FontStyle.Bold)
    
                    For x As Single = 0 To TimeMax Step xStep
                        .DrawLine(p, x, 0, x, yMax)
                        .DrawString(x.ToString, f, br, x, 0)
                    Next
    
                    Dim y As Single = CSng(0.5 * InsidePic.ClientSize.Height / sr)
    
                    .DrawLine(p2, 0, y, TimeMax, y)
                    .DrawString(" Seconds", f, br, 0, f.Height)
    
                    For Each x As Integer In pts
                        .DrawEllipse(p3, New RectangleF(x, CSng(0.7 * y), CSng(6 / sr), CSng(6 / sr)))
                    Next
                End Using
            End With
        End Sub
    
        Private Sub HScroll1_ValueChanged(sender As Object, e As EventArgs) Handles HScroll1.ValueChanged
            Dim dx As Integer = CInt(1.1 * OutsidePic.ClientSize.Width - InsidePic.ClientSize.Width)
            InsidePic.Location = New Point(CInt(HScroll1.Value * dx / 100), 0)
        End Sub
    
        Private Sub Form5_MouseWheel(sender As Object, e As MouseEventArgs) Handles Me.MouseWheel
            ScaleRatio += Math.Sign(e.Delta) * 0.1
            If ScaleRatio > 5 Then ScaleRatio = 5
            If ScaleRatio < 0.1 Then ScaleRatio = 0.1
            InsidePic.Invalidate()
        End Sub
    End Class


    seems really promising! I'll test it out asap and I give you my feedback at once. Thanks a million
    Wednesday, April 24, 2019 9:59 PM
  • Hi,

    Is your problem solved? If so, please mark the useful replies as answers.  

    Best Regards,

    Alex


    MSDN Community Support Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Friday, April 26, 2019 6:41 AM
  • This is the famous picturebox inside a picturebox method of scrolling.

    Since your data is static ie you have a song with a fixed time length this approach is easy.

    With this method the timeline is drawn full length on a picturebox width that is inside a second parent or outside picturebox. Then the inside picturebox is moved directly with the scrollbar.

    The inside pic is 3 x the outside then you can scroll from end to end with one scrollbar range. The scroll bar range is 0 to 100 and then ratio that to the innerpic width.

    To draw a seconds grid just spread the TimeMax across the width of the inside pic. Timemax is the length of the song in sec. So the grid is from 0 to timemax across the width of the picturebox.

    One can work on something like this endlessly this is just a start.

    :)

    The example makes the controls just cut and paste into an empty form, change the form name as reqd.

     

    Public Class Form5
        Private WithEvents OutsidePic As New PictureBox With {.Parent = Me, .BorderStyle = BorderStyle.FixedSingle}
        Private WithEvents InsidePic As New PictureBox With {.Parent = OutsidePic, .BorderStyle = BorderStyle.FixedSingle}
        Private WithEvents HScroll1 As New HScrollBar With {.Parent = OutsidePic, .Maximum = 100,
            .Minimum = 0, .SmallChange = 1, .Dock = DockStyle.Bottom}
        Private Border As Integer = 20
        Private InnerHeight As Integer = 200
        Private TimeMax As Integer = 240 'seconds
        Private ScaleRatio As Double = 1
        Private pts As New List(Of Integer)
        '
        Private Sub Form5_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            ClientSize = New Size(500, 300)
            BackColor = Color.DimGray
            OutsidePic.BackColor = Color.Black
            InsidePic.BackColor = Color.White
            OutsidePic.Location = New Point(Border, Border)
            TimeMax = 240  'this is the length of this song in seconds
            pts.Add(30)
            pts.Add(67)
            pts.Add(122)
            HScroll1.Value = 0
            HScroll1.BringToFront()
    
            Form5_Resize(0, Nothing)
        End Sub
    
        Private Sub Form5_Resize(sender As Object, e As EventArgs) Handles Me.Resize
    
            OutsidePic.ClientSize = New Size(ClientSize.Width - (2 * Border), InnerHeight)
    
            'set inside width to show the time max on the current window size
            Dim w As Integer = CInt(3 * OutsidePic.ClientSize.Width)
            If w < 10 Then w=10
    
            InsidePic.ClientSize = New Size(w, InnerHeight)
    
            InsidePic.Invalidate()
        End Sub
    
        Private Sub InsidePic_Paint(sender As Object, e As PaintEventArgs) Handles InsidePic.Paint
            Dim xStep As Integer
    
            Select Case TimeMax
                Case < 50
                    xStep = 2
                Case < 100
                    xStep = 5
                Case < 100
                    xStep = 10
                Case < 500
                    xStep = 20
                Case Else
                    xStep = 50
            End Select
    
            Dim sr As Single = CSng(ScaleRatio * InsidePic.ClientSize.Width / TimeMax)
            Dim yMax As Integer = InsidePic.Height
    
            With e.Graphics
                .ScaleTransform(sr, sr)
    
                Using p As New Pen(Color.SkyBlue, CSng(sr / 100)),
                        p2 As New Pen(Color.Lime, CSng(sr / 50)),
                        p3 As New Pen(Color.Red, CSng(sr / 10)),
                        br As New SolidBrush(Color.LightGray),
                        f As New Font("tahoma", CSng(10 / sr), FontStyle.Bold)
    
                    For x As Single = 0 To TimeMax Step xStep
                        .DrawLine(p, x, 0, x, yMax)
                        .DrawString(x.ToString, f, br, x, 0)
                    Next
    
                    Dim y As Single = CSng(0.5 * InsidePic.ClientSize.Height / sr)
    
                    .DrawLine(p2, 0, y, TimeMax, y)
                    .DrawString(" Seconds", f, br, 0, f.Height)
    
                    For Each x As Integer In pts
                        .DrawEllipse(p3, New RectangleF(x, CSng(0.7 * y), CSng(6 / sr), CSng(6 / sr)))
                    Next
                End Using
            End With
        End Sub
    
        Private Sub HScroll1_ValueChanged(sender As Object, e As EventArgs) Handles HScroll1.ValueChanged
            Dim dx As Integer = CInt(1.1 * OutsidePic.ClientSize.Width - InsidePic.ClientSize.Width)
            InsidePic.Location = New Point(CInt(HScroll1.Value * dx / 100), 0)
        End Sub
    
        Private Sub Form5_MouseWheel(sender As Object, e As MouseEventArgs) Handles Me.MouseWheel
            ScaleRatio += Math.Sign(e.Delta) * 0.1
            If ScaleRatio > 5 Then ScaleRatio = 5
            If ScaleRatio < 0.1 Then ScaleRatio = 0.1
            InsidePic.Invalidate()
        End Sub
    End Class

    I tested your suggestion and worked on it for hours. This is a very cool idea to make a neat timeline.

    I tried to make the HScroll1 scrolls automatically as music plays and goes on (just like the trackbar I mentioned earlier). It works as expected, but not really precise as the scroll bar's thumb is bigger than a vertical line to point out the current music position. Is it possible to draw a vertical line instead? the one that moves forward every second the music goes on , on the InsidePic ?

    Like the blue vertical line in the attached picture.

    Furthermore, by creating new List(Of Integer) , it is possible to prevent new reminder points hiding previously created ones if their creation time is identical.

    Actually I defined an integer (Yp) with value of 10 and I also defined pts2 as a new List(Of Integer) , then :

     Private Sub InsidePic_Paint(sender As Object, e As PaintEventArgs) Handles InsidePic.Paint
            Dim xStep As Integer
    
            Select Case TimeMax
                Case < 50
                    xStep = 2
                Case < 100
                    xStep = 5
                Case < 100
                    xStep = 10
                Case < 500
                    xStep = 20
                Case Else
                    xStep = 50
            End Select
    
            Dim sr As Single = CSng(ScaleRatio * 1200 / TimeMax)
            Dim yMax As Integer = 100
    
            With e.Graphics
                .ScaleTransform(sr, sr)
    
                Using p As New Pen(Color.RoyalBlue, CSng(sr / 100)),
                        p2 As New Pen(Color.RoyalBlue, CSng(sr / 50)),
                        p3 As New Pen(Color.Purple, CSng(sr / 5)),
                        br As New SolidBrush(Color.LightGray),
                        f As New Font("Segoe UI", CSng(10 / sr), FontStyle.Bold)
    
                    For x As Single = 0 To TimeMax Step xStep
                        .DrawLine(p, x, 0, x, yMax)
                        .DrawString(x.ToString, f, br, x, 0)
                    Next
    
                    Dim y As Single = CSng(0.5 * InsidePic.ClientSize.Height / sr)
    
                    .DrawLine(p2, 0, y, TimeMax, y)
                    .DrawString(" Seconds", f, br, 0, f.Height)
    
                    For Each x As Integer In pts
                        .DrawEllipse(p3, New RectangleF(x, CSng(0.7 * y), CSng(6 / sr), CSng(6 / sr)))
                    Next
    
                    For Each x As Integer In pts2
                        .DrawEllipse(p3, New RectangleF(x, CSng(0.7 * y + Yp), CSng(6 / sr), CSng(6 / sr)))
                    Next
    
                End Using
            End With
        End Sub

    Now, if there are :  pts.add(30)      and      pts2.add(30)

    The reminder points never hide each other because they aren't created on the same line level.




    • Edited by Kevin993 Friday, April 26, 2019 10:07 AM
    Friday, April 26, 2019 10:03 AM
  • Kevin,

    "Is it possible to draw a vertical line instead?"

    Yes. Look at how I did the one in the draw wav example I gave you above.

    You have PlayerControl.Ctlcontrols.currentPosition so you just draw a line at that time. So you need an event and you need to draw the postion on the time line. In fact just redraw the entire time line with the position line. See how I did it in the wav example. Give it a try.


    "The reminder points never hide each other because they aren't created on the same line level."

    Yup. Good.

    Like I said you can work on it endlessly.

    Friday, April 26, 2019 12:56 PM