Results 1 to 23 of 23

Thread: [RESOLVED] Drawing on a Track Bar

  1. #1

    Thread Starter
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    38,988

    Resolved [RESOLVED] Drawing on a Track Bar

    I'm thinking of an interface that will have a track bar which can have vertical lines of different colors drawn on it at certain points. I note that the track bar doesn't appear to have a Paint event, which seems to rule out my first thought, which was just painting onto the track bar itself.

    Another possibility is to create my own. I did this for a slider that has a fish as the 'thumb button', so I could certainly do something like that again. That's a bit more of a nuisance, though, because my other custom slider didn't have (or need) the ticks on the standard track bar control. I'd like to have those, and the thumb button has to go over the extra color lines, rather than behind it.

    Before I head off to making my own control, I thought I'd ask whether or not anybody has any other suggestion. The goal is a track bar with extra lines of emphasis that may or may not be on existing track bar ticks. The goal is to show a range of dates (the ticks), and indicate when events happened during that range of dates.
    My usual boring signature: Nothing

  2. #2
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,598

    Re: Drawing on a Track Bar

    Overriding OnPaint doesn't work at all for whatever reason but I have been successful in handling painting more directly through the Control's Window Procedure.
    vbnet Code:
    1. Public Class TrackBarEx
    2.     Inherits TrackBar
    3.  
    4.     Protected Overrides Sub WndProc(ByRef m As Message)
    5.  
    6.         Const WM_PAINT As Integer = &HF
    7.  
    8.         If m.Msg = WM_PAINT Then
    9.  
    10.             'Draw the control as normal
    11.             MyBase.WndProc(m)
    12.  
    13.             'Add a border around it
    14.             DrawControl()
    15.             Exit Sub
    16.         End If
    17.  
    18.         MyBase.WndProc(m)
    19.     End Sub
    20.  
    21.     Private Sub DrawControl()
    22.         Using g As Graphics = Me.CreateGraphics
    23.             DrawBorder(g, Color.Red, 3)
    24.         End Using
    25.     End Sub
    26.  
    27.     Private Sub DrawBorder(ByVal g As Graphics, ByVal c As Color, ByVal thickness As Integer)
    28.         Dim rect As Rectangle = New Rectangle(0, 0, Me.ClientRectangle.Width - 1, Me.ClientRectangle.Height - 1)
    29.  
    30.         Using p As Pen = New Pen(c)
    31.  
    32.             For i = 0 To thickness - 1
    33.                 g.DrawRectangle(p, New Rectangle(i, i, rect.Width - i * 2, rect.Height - i * 2))
    34.             Next
    35.  
    36.         End Using
    37.  
    38.  
    39.     End Sub
    40.  
    41. End Class

    Which produces this:-


    I've created a derived class that draws a border around the control. There is a slight quirk though. When dragging the control on a Form in design mode, the control renders normally for the duration of the drag operation, effectively ignoring my custom painting code. I have no idea why. However, it seems to work acceptably otherwise.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  3. #3
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    25,464

    Re: Drawing on a Track Bar

    @Niya... Great workaround. Does the thumb render over any drawing on the control? My guess is that'll need some work on it...

  4. #4
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,598

    Re: Drawing on a Track Bar

    Quote Originally Posted by .paul. View Post
    @Niya... Great workaround. Does the thumb render over any drawing on the control? My guess is that'll need some work on it...
    Well it depends on whether you call the base class WndProc before or after the custom rendering code. You can think of calling the base class WndProc as calling the default drawing code and apply normal logic there. That is whatever is drawn second will overdraw whatever was drawn first. The code I posted draws the control first and then the custom code draws over it. Doing it the other way around, that is to say drawing the control over the custom draws works but it's a bit quirky. For example, it would appear to paint normally without the custom code when the control is first rendered when the form is loaded. The custom code only appears working after passing the mouse over the control.

    My overall impression of this method of custom drawing the TrackBar control is that it's only good for something quick and simple. Hijacking a Control's painting like this produces too many quirks and abhorrent behaviors. I would never use this method for anything other than simple things like drawing a border or rendering some text. If I wanted to do something more complicated, I'd write my own from scratch or inherit from the TrackBar Control like I did here but I'd completely disable the default drawing code and override OnPaint:-
    vbnet Code:
    1. Me.SetStyle(ControlStyles.UserPaint, True)

    The above should be placed in the constructor and would completely disable the default rendering code and allow you to draw whatever you want by overriding OnPaint. This should also work with any Control, not just the TrackBar.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  5. #5

    Thread Starter
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    38,988

    Re: Drawing on a Track Bar

    Well, that suggests that I'd be better off just rolling my own. Drawing the tick marks is a nuisance, but not a bad one. Better yet, I can use a fish as the thumb button.
    My usual boring signature: Nothing

  6. #6
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    25,464

    Re: Drawing on a Track Bar

    Quote Originally Posted by Shaggy Hiker View Post
    Well, that suggests that I'd be better off just rolling my own. Drawing the tick marks is a nuisance, but not a bad one. Better yet, I can use a fish as the thumb button.
    I know you’re a marine biologist, but I don’t see the advantage of using the fish thumb??? ��

  7. #7

    Thread Starter
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    38,988

    Re: Drawing on a Track Bar

    There isn't an advantage. It's just fun.

    Fish make good arrows. They tend to be relatively long to their width, with pointed heads. At the very least, you can always choose a fish that makes a good arrow (not the literal kind, they don't don't usually fly straight). My programs are fish related, so there's always something fishy about whatever I do.
    My usual boring signature: Nothing

  8. #8
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,598

    Re: Drawing on a Track Bar

    I realize this topic is old and it's generally a bad practice to bump these old threads but upon reviewing the approach I suggested as a possibility I feel strongly compelled to revisit this given what I've been doing for the past month or so. I've committed myself to the rewrite of a very large application and I've decided to take a serious look at rewriting this application in something a bit more modern and less messy than WinForms. So for the past month or so I've dived head long into WPF. Given what I've learned so far, I felt very strongly that I needed to revisit this topic

    I looked at the method of modifying the TrackBar I suggested and even when I worked it out and posted it, I still felt it was dirty, clunky and severely limited. But that was the best I could do given WinForms' limits. However, I've discovered that WPF can do EXACTLY what you need in a very clean and manageable way and given that fact I think it was necessary to bump to thread to bring it to light as a suggestion.

    Now I'm still in the learning stages and haven't played with the Sliders yet in my WPF adventures but I have found what others have been able to do online:-




    The above images are all of custom TrackBars done in WPF. You can check out the details behind them in these StackOverflow threads:-
    https://stackoverflow.com/questions/...image-as-thumb
    https://stackoverflow.com/questions/...mplate-for-wpf

    One of the things I've learned about WPF is that when it comes to UI design and control customization, it is leagues ahead of Winforms. In fact, I don't think I will EVER be able to go back to WinForms after using WPF. It is just far better, especially at this kind of thing. And Shaggy might also appreciate the fact that WPF is hardware accelerated. DirectX sits at WPF's backend, not GDI+ like in WinForms.

    In WPF you no longer have to rely of all of these messy and highly technical subclassing wizardry to modify controls. WPF controls were built from the ground up with customization in mind. You can do some extremely powerful visual customization of controls without any kind of subclassing whatsoever and what's more is that it generally takes far less code and LOT less technical knowledge. You know longer have to think about overriding window procedures and spend hours hunting down constants and Win32 API P/Invoke signatures or any of that messy time consuming stuff you need to do with WinForms and VB6.

    So I'd suggest you take a serious look at WPF if you find yourself needing to do this kind of thing often. Now I'm not gonna lie, WPF has a steep learning curve but nothing I would consider insurmountable. I'm still learning but I'm already quite comfortable with WPF's way of doing things and only took me about a month. Best of all, it feels great. Despite the steeper learning curve and a bit more complexity in a few places(eg. Dependency properties), it's difficult to find a reason to continue using WinForms over WPF. It does a lot of things so much better. I strongly recommend you get into this if you do a lot of UI stuff.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  9. #9
    Lively Member
    Join Date
    Jan 2020
    Posts
    120

    Re: Drawing on a Track Bar

    Code:
    Public Class Form1
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            TrackBar1.Minimum = 0
            TrackBar1.Maximum = 11    ' 0 to 11 will be 12 Ticks
            TrackBar1.SmallChange = 1
            TrackBar1.LargeChange = 1
            TrackBar1.Value = 0
        End Sub
    
        Private Sub Panel1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Panel1.Paint
            Dim dpw As Double = ((Panel1.Width - 1) / ((TrackBar1.Maximum - TrackBar1.Minimum) / TrackBar1.TickFrequency))
            Dim tmp As Double = 0
            For x As Integer = 0 To CInt(((TrackBar1.Maximum - TrackBar1.Minimum) / TrackBar1.TickFrequency))
                Dim i As Integer = CInt(tmp)
                If i > Panel1.Width - 1 Then i = Panel1.Width - 1
                If x <= TrackBar1.Value Then
                    e.Graphics.DrawLine(Pens.Red, i, 0, i, e.ClipRectangle.Height)
                Else
                    e.Graphics.DrawLine(Pens.Black, i, 0, i, e.ClipRectangle.Height)
                End If
                tmp += dpw
            Next
        End Sub
    
        Private Sub TrackBar1_ValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles TrackBar1.ValueChanged
            Panel1.Refresh() 'Repaints the panel so the tick marks will change color as the value changes
        End Sub
    End Class

  10. #10
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,598

    Re: Drawing on a Track Bar

    Quote Originally Posted by Prahlad View Post
    Code:
    Public Class Form1
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            TrackBar1.Minimum = 0
            TrackBar1.Maximum = 11    ' 0 to 11 will be 12 Ticks
            TrackBar1.SmallChange = 1
            TrackBar1.LargeChange = 1
            TrackBar1.Value = 0
        End Sub
    
        Private Sub Panel1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Panel1.Paint
            Dim dpw As Double = ((Panel1.Width - 1) / ((TrackBar1.Maximum - TrackBar1.Minimum) / TrackBar1.TickFrequency))
            Dim tmp As Double = 0
            For x As Integer = 0 To CInt(((TrackBar1.Maximum - TrackBar1.Minimum) / TrackBar1.TickFrequency))
                Dim i As Integer = CInt(tmp)
                If i > Panel1.Width - 1 Then i = Panel1.Width - 1
                If x <= TrackBar1.Value Then
                    e.Graphics.DrawLine(Pens.Red, i, 0, i, e.ClipRectangle.Height)
                Else
                    e.Graphics.DrawLine(Pens.Black, i, 0, i, e.ClipRectangle.Height)
                End If
                tmp += dpw
            Next
        End Sub
    
        Private Sub TrackBar1_ValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles TrackBar1.ValueChanged
            Panel1.Refresh() 'Repaints the panel so the tick marks will change color as the value changes
        End Sub
    End Class
    How is this meant to work? All it does is draw ticks on a panel in response to TrackBar being manipulated. It is certainly an interesting piece of code but I don't see how this can be used for changing a TrackBar's appearance.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  11. #11
    PowerPoster ChrisE's Avatar
    Join Date
    Jun 2017
    Location
    Frankfurt
    Posts
    3,040

    Re: Drawing on a Track Bar

    don't know if this is an option for you.
    If I want to show somthing that happens within a Daterange I allways go with a Calendar. The Image below
    shows the status of an Employee... Sick, Holiday etc.. and counts the occurance of each.

    I use the same sort of thing for Projects... start of Project; Progress of the Project, things that go wrong along the way
    and indicate that with diffrent colors

    perhaps an Idea

    here the Image
    Name:  CalHorizontal.jpg
Views: 1569
Size:  44.7 KB
    to hunt a species to extinction is not logical !
    since 2010 the number of Tigers are rising again in 2016 - 3900 were counted. with Baby Callas it's 3901, my wife and I had 2-3 months the privilege of raising a Baby Tiger.

  12. #12
    Fanatic Member Delaney's Avatar
    Join Date
    Nov 2019
    Location
    Paris, France
    Posts
    845

    Re: Drawing on a Track Bar

    Quote Originally Posted by Prahlad View Post
    Code:
    Public Class Form1
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            TrackBar1.Minimum = 0
            TrackBar1.Maximum = 11    ' 0 to 11 will be 12 Ticks
            TrackBar1.SmallChange = 1
            TrackBar1.LargeChange = 1
            TrackBar1.Value = 0
        End Sub
    
        Private Sub Panel1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Panel1.Paint
            Dim dpw As Double = ((Panel1.Width - 1) / ((TrackBar1.Maximum - TrackBar1.Minimum) / TrackBar1.TickFrequency))
            Dim tmp As Double = 0
            For x As Integer = 0 To CInt(((TrackBar1.Maximum - TrackBar1.Minimum) / TrackBar1.TickFrequency))
                Dim i As Integer = CInt(tmp)
                If i > Panel1.Width - 1 Then i = Panel1.Width - 1
                If x <= TrackBar1.Value Then
                    e.Graphics.DrawLine(Pens.Red, i, 0, i, e.ClipRectangle.Height)
                Else
                    e.Graphics.DrawLine(Pens.Black, i, 0, i, e.ClipRectangle.Height)
                End If
                tmp += dpw
            Next
        End Sub
    
        Private Sub TrackBar1_ValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles TrackBar1.ValueChanged
            Panel1.Refresh() 'Repaints the panel so the tick marks will change color as the value changes
        End Sub
    End Class
    you could at least give your source... https://social.msdn.microsoft.com/Fo...orum=vbgeneral
    The best friend of any programmer is a search engine
    "Don't wish it was easier, wish you were better. Don't wish for less problems, wish for more skills. Don't wish for less challenges, wish for more wisdom" (J. Rohn)
    “They did not know it was impossible so they did it” (Mark Twain)

  13. #13
    Fanatic Member Delaney's Avatar
    Join Date
    Nov 2019
    Location
    Paris, France
    Posts
    845

    Re: Drawing on a Track Bar

    Quote Originally Posted by Shaggy Hiker View Post
    I'm thinking of an interface that will have a track bar which can have vertical lines of different colors drawn on it at certain points. I note that the track bar doesn't appear to have a Paint event, which seems to rule out my first thought, which was just painting onto the track bar itself.

    Another possibility is to create my own. I did this for a slider that has a fish as the 'thumb button', so I could certainly do something like that again. That's a bit more of a nuisance, though, because my other custom slider didn't have (or need) the ticks on the standard track bar control. I'd like to have those, and the thumb button has to go over the extra color lines, rather than behind it.

    Before I head off to making my own control, I thought I'd ask whether or not anybody has any other suggestion. The goal is a track bar with extra lines of emphasis that may or may not be on existing track bar ticks. The goal is to show a range of dates (the ticks), and indicate when events happened during that range of dates.
    Some ideas found here :https://www.codeproject.com/Articles...Control-VB-NET
    The best friend of any programmer is a search engine
    "Don't wish it was easier, wish you were better. Don't wish for less problems, wish for more skills. Don't wish for less challenges, wish for more wisdom" (J. Rohn)
    “They did not know it was impossible so they did it” (Mark Twain)

  14. #14
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,598

    Re: Drawing on a Track Bar

    Quote Originally Posted by Delaney View Post
    While this is truly impressive. I'd like to point out for the record that WPF allows that level of customization on ANY control with a fraction of the code. Not that Shaggy should ignore this option, but I just wanted to make it clear why I thought WPF is a worthwhile investment to learn. If you find yourself wanting to do this level of customization often then WPF should be considered for future development efforts.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  15. #15
    PowerPoster
    Join Date
    Nov 2017
    Posts
    3,116

    Re: Drawing on a Track Bar

    Quote Originally Posted by Delaney View Post
    you could at least give your source... https://social.msdn.microsoft.com/Fo...orum=vbgeneral
    Every single one of Prahlad's posts that I've ever looked at are complete copy/paste jobs of content from other websites.

  16. #16
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,598

    Re: Drawing on a Track Bar

    Quote Originally Posted by OptionBase1 View Post
    Every single one of Prahlad's posts that I've ever looked at are complete copy/paste jobs of content from other websites.
    Ya, I just looked at his post history. Pretty low effort content but it's some effort I guess.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  17. #17
    Fanatic Member Delaney's Avatar
    Join Date
    Nov 2019
    Location
    Paris, France
    Posts
    845

    Re: Drawing on a Track Bar

    yep, it is at least the search effort.
    The best friend of any programmer is a search engine
    "Don't wish it was easier, wish you were better. Don't wish for less problems, wish for more skills. Don't wish for less challenges, wish for more wisdom" (J. Rohn)
    “They did not know it was impossible so they did it” (Mark Twain)

  18. #18

    Thread Starter
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    38,988

    Re: Drawing on a Track Bar

    It took me a while to remember what this was about. I solved it a long time back, though. In general, WPF is out of the question, currently, for complicated reasons.
    My usual boring signature: Nothing

  19. #19
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,219

    Re: Drawing on a Track Bar

    Regarding Delaneys Link to a conventional written Slider-Control:
    https://www.codeproject.com/Articles...Control-VB-NET

    Quote Originally Posted by Niya View Post
    While this is truly impressive.
    I'd like to point out for the record that WPF allows that level of customization on ANY control with a fraction of the code.
    Nah...

    With a good Graphics- and WidgetLib, a well-written conventional Control is usually:
    - comparable to WPF (regarding Lines-of-Code)
    - much easier to understand
    - much easier to maintain
    - and also easy to "visually inherit"

    Take for example this conventionally written cwSlider-Widget (which duplicates this WPF-Control):
    https://stackoverflow.com/questions/...mplate-for-wpf



    The implementation in cwSlider features:
    - with about 70 lines, less code (compared to the WPF-example)
    - and that whilst *not* using a pre-existing Slider-Ctl (it is implemented entirely "from scratch")
    - it is easier to read (no magic, just DrawLine and DrawText drawing-commands)
    - it has full KeyBoard-support (reacting to the ArrowKeys)
    - it has proper Tabbing- and Focus-support (highlighting the focused state)
    - and also comes with automatic Horizontal/Vertical detection
    .. (when the Ctl-Width is smaller than its Height, it switches to vertical rendering)

    So I'm quite sure that - in case you want to expand the WPF-example to the same functionality -
    you'd have to struggle quite a bit - ending up with even more XML-Lines...

    And as for "visual inheritance", I've tried to cover that in my Demo as well,
    taking up Shaggy's idea, imlementing a cwSliderFish... ... (which you see at the bottom and to the right of the ScreenShot).

    The CodeBank-entry is here:
    https://www.vbforums.com/showthread....Horz-Switching

    For those interested, here the implementation of cwSliderFish (making use of the already existing cwSlider - without any Window-Subclassing):
    Code:
    Option Explicit
     
    Private WithEvents W As cWidgetBase
    
    Public Event Change()
    Public WithEvents S As cwSlider
    
    Private Sub Class_Initialize()
      Set S = New cwSlider  'create a new (normal) cwSlider-instance
      Set W = S.Widget 'now cast our internal WidgetBase to it (instead of creating a virginal Widgetbase-instance)
    End Sub
    
    'default-Prop-Implementation (needed in any Widget-Class)
    Public Property Get Widget() As cWidgetBase:  Set Widget = W: End Property
    Public Property Get Widgets() As cWidgetBase: Set Widgets = W.Widgets: End Property
    
    Private Sub S_Change()
      RaiseEvent Change 'delegate the inherited Event
    End Sub
    
    'here we are able to add our own stuff, via the inherited Paint-Event
    Private Sub W_Paint(CC As RC6.cCairoContext, ByVal xAbs As Single, ByVal yAbs As Single, ByVal dx_Aligned As Single, ByVal dy_Aligned As Single, UserObj As Object)
      Dim v: v = W.Width < W.Height
      Dim x: x = (IIf(v, W.Height, W.Width) - 2 * S.Offs) * (S.Value - S.Min) / (S.Max - S.Min)
      
      If Len(W.ImageKey) Then 'we probably have a fishy *.png behind that Key...
         CC.RenderSurfaceContent W.ImageKey, IIf(v, W.Width - 21, x), IIf(v, W.Height - x - 24, 1), 21, 21, CAIRO_FILTER_BEST
      End If
    End Sub
    Olaf

  20. #20
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,598

    Re: Drawing on a Track Bar

    Quote Originally Posted by Schmidt View Post
    Nah...
    Not so fast. Lines of code written is not the only important metric here when weighing the benefits of WPF over WinForms. Productivity is arguable a more important metric. Now I am willing to concede for this topic of the Slider control, the complexity is roughly the same across all the examples we've seen here(VB6, WinForms and WPF). However, in general, designing UIs in WPF is far superior to WinForms. It offers a flexibility that would cost far too much in productivity if we tried to do the same things using WinForms. For the purposes of this discussion, I'll define productivity as the time between coming up with an idea and making that idea a reality. I'll give an example of the contrast between the two technologies.

    Lets say you're developing an application in WinForms and at some point you need to give the user the ability to pick a colour from a list of predefined colours. Lets say this colour is meant to be used to colour some text. You might be thinking that a ComboBox would be nice for this. So you dive right in and after about 15 minutes you come up with this:-
    vbnet Code:
    1. Public Class ColorListCombo
    2.     Inherits ComboBox
    3.  
    4.     Sub New()
    5.         Me.DropDownStyle = ComboBoxStyle.DropDownList
    6.         Me.DrawMode = DrawMode.OwnerDrawVariable
    7.         Me.DropDownHeight = 400
    8.         Me.DropDownWidth = Me.Width
    9.     End Sub
    10.  
    11.     Protected Overrides Sub OnMeasureItem(e As MeasureItemEventArgs)
    12.         e.ItemHeight = 40
    13.  
    14.         MyBase.OnMeasureItem(e)
    15.     End Sub
    16.  
    17.     Protected Overrides Sub OnDrawItem(e As DrawItemEventArgs)
    18.  
    19.         If e.Index < 0 Then Return
    20.  
    21.         Dim text As String = "How it looks as text"
    22.         Dim item As Color = Me.Items.Item(e.Index)
    23.         Dim textSize As SizeF = e.Graphics.MeasureString(text, Me.Font)
    24.  
    25.         Dim colorBounds As Rectangle = e.Bounds
    26.         Dim textBounds As RectangleF = New RectangleF(colorBounds.Right,
    27.                                                       e.Bounds.Y + (e.Bounds.Height / 2) - (textSize.Height / 2),
    28.                                                       textSize.Width,
    29.                                                       textSize.Height)
    30.  
    31.  
    32.         colorBounds.Width = e.Bounds.Height
    33.  
    34.         textBounds.X = colorBounds.Right
    35.         textBounds.Width = e.Bounds.Width - colorBounds.Right
    36.  
    37.         e.DrawBackground()
    38.  
    39.         Using b As New SolidBrush(item)
    40.             e.Graphics.FillRectangle(b, colorBounds)
    41.             e.Graphics.DrawString(text, Me.Font, b, textBounds)
    42.         End Using
    43.  
    44.     End Sub
    45.  
    46. End Class


    The problem here is that this is a huge productivity drain. Why? Because you have to tell the UI how to do what you want. I have to calculate the offsets and bounding boxes. Then I have to draw the string and the colours using the calculations I made. If I'm on a deadline, I really don't want to waste time calculating offsets and bounding boxes and typing out a bunch of parameters for drawing calls etc?

    This piece of code in particular is a huge productivity drain:-
    vbnet Code:
    1. Dim textBounds As RectangleF = New RectangleF(colorBounds.Right,
    2.                                                       e.Bounds.Y + (e.Bounds.Height / 2) - (textSize.Height / 2),
    3.                                                       textSize.Width,
    4.                                                       textSize.Height)

    All it does is center the text vertically. Look at how verbose that is. We are doing a bunch of math, calling a constructor and making 6 property calls. All that just to center a piece of text? And because of how verbose it is, it's easy to make mistakes and every time you have to run your app and go back to correct it is a productivity drain. Is the cost really worth what you're buying? When you most likely have a 100 more important things to do in your application do you really want to spend all this time on such a tiny detail like centering a piece of text?

    Wouldn't it be nice if you could tell the computer what you want instead of how to do it? Well this is where WPF shines:-
    xaml Code:
    1. '
    2.         <ComboBox Name="cmb" Width="300" Height="21">
    3.             <ComboBox.ItemTemplate>
    4.                 <DataTemplate>
    5.                     <StackPanel Orientation="Horizontal">
    6.                         <StackPanel.Resources>
    7.                             <SolidColorBrush x:Key="color" Color="{Binding}"/>
    8.                         </StackPanel.Resources>
    9.  
    10.                         <Rectangle Height="40" Width="40" Fill="{StaticResource color}"/>
    11.  
    12.                         <TextBlock Foreground="{StaticResource color}" VerticalAlignment="Center">How it looks as text</TextBlock>
    13.                     </StackPanel>
    14.                 </DataTemplate>
    15.             </ComboBox.ItemTemplate>
    16.         </ComboBox>


    That's all it took in WPF. Notice here I don't have to spend any effort calculating bounding boxes and offsets. I don't have to write any drawing code to render the text or the coloured rectangle. I don't have to do any of that. I just tell WPF what I want and it knows how to do it. And remember that calculation in the WinForms example for vertically centering the text? Well this is all it took in WPF:-
    xaml Code:
    1. VerticalAlignment="Center"

    Concise and straight to the point about what I want. It's difficult to screw that up. Most of my focus could be spent on actually developing the application rather than tinkering with offsets and bounding boxes . Why would you want to give yourself all this extra work when you don't have to?

    Now lets throw a wrench in the plan. Lets say your user wants the ability to remove colours from the list. You as the WPF programmer might decide you want to embed a Button right next to the coloured text to do this. What would it cost in terms of productivity? Well, it costs a single line of text:-
    xaml Code:
    1. <Button Margin="25,0,0,0" Width="70" Height="25" >Remove</Button>

    You place the above XAML under the <TextBlock> and you get this:-


    You now have a Button for each item in the ComboBox's list. If I were doing this in WinForms, I'd have a choice to make. Do I want to spend the next several hours trying to figure out how to tell VB to place a Button next to each item in a ComboBox, or do I want to settle for a more boring solution and get on with writing the application? If I'm working with some kind of deadline that's drawing close and I still have a lot of work to do on the rest of the application, I would have to settle for a solution that's easier to implement.

    Now there is nothing wrong with settling. We do it all the time as programmers and it's part of writing programs, especially when deadlines are involved but that doesn't mean we shouldn't want more productive tools to build our applications. Building the UIs we want is more productive in WPF than it is trying to build the same UI in WinForms. We can get more out of it for less time spent. Why would we not want to take advantage of that?

    WPF allows you such an insane degree of flexibility with UI design. Can the same things be done in WinForms? Yes, but that's not the point, the point is how productive would it be trying to bend WinForms to implement your UIs the way you want. You don't have to do too much bending with WPF. You can pretty much tell it how you want your UIs to look and it can do it more often than not and you can be pretty outrageous with it if you want.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  21. #21

    Thread Starter
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    38,988

    Re: [RESOLVED] Drawing on a Track Bar

    @Olaf: That's a nice slider. I'm graphically challenged, so it's no surprise when somebody can come up with a nicer looking control than anything I think up. You used a couple graphical choices there that I rather like, though my fish is better (salmonids make better pointers). Still, you gave me some ideas on how to improve the appearance of my sliders. I was drawing lines when certain events happened, but coloring segments of the slider has the potential to better represent the situation to the user.

    @Niya: WPF has some even greater benefits, for my purposes, as it will use the GPU pretty much automatically, and opens up simple inclusion of XNA/MonoGame, which I found essential. However, I wasn't allowed to use WPF when I started out, and while I could move to it now, I'm using a plugin system, so it's not necessarily up to me what plugin writers use. As long as the pieces can be integrated (they can be), then people are free to use whatever they want.

    Still, when the door was closed for me using WPF, I left it closed, and will continue to do so. The use of the GPU, the ability of controls to bubble events up the stack, and so on, are all somewhat appealing features of WPF. Somewhat, that is, until I remember that I can barely draw a rectangle, let alone anything more artistic.
    My usual boring signature: Nothing

  22. #22
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,598

    Re: [RESOLVED] Drawing on a Track Bar

    Quote Originally Posted by Shaggy Hiker View Post
    Still, when the door was closed for me using WPF, I left it closed, and will continue to do so. The use of the GPU, the ability of controls to bubble events up the stack, and so on, are all somewhat appealing features of WPF. Somewhat, that is, until I remember that I can barely draw a rectangle, let alone anything more artistic.
    If your application is data driven without any fancy UI customizations, you can still benefit from WPF because of it's extremely powerful data-binding capabilities.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  23. #23

    Thread Starter
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    38,988

    Re: [RESOLVED] Drawing on a Track Bar

    It's all UI customizations, though I'm not sure I'd call them fancy. It's a line of business app done as a game interface.
    My usual boring signature: Nothing

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width