Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. .NET (Core and Framework)
  4. Combobox - DrawItem and dragging scroll bar problem

Combobox - DrawItem and dragging scroll bar problem

Scheduled Pinned Locked Moved .NET (Core and Framework)
graphicshelpdatabase
7 Posts 2 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    D Offline
    David Hovey
    wrote on last edited by
    #1

    Hi there. I need some help with drawing items for a ComboBox Control. For the most part the ComboBox draws just fine. I can scroll up and down and everything is good. The problem is when I drag the scrollbar "thumb" or box to get through the list faster. The items do not display correctly. The ComboBox is set to DropDownList and OwnerDrawVariable. I understand the code below is not very meaningful as I could use the windows implementation to draw the items. The program I'm working on displays certain items in bold, so the code below just illustrates the problem I have. Thanks for your help!!

    Public Class Form1

    Private Sub Button1\_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    
        Dim i As Integer
    
        For i = 1 To 200
            ComboBox1.Items.Add(i)
        Next
    
    End Sub
    
    Private Sub ComboBox1\_DrawItem(ByVal sender As Object, ByVal e As System.Windows.Forms.DrawItemEventArgs) Handles ComboBox1.DrawItem
    
        If e.Index = -1 Then
            Exit Sub
        End If
    
        e.DrawBackground()
    
        e.Graphics.DrawString(ComboBox1.Items(e.Index).ToString(), e.Font, New SolidBrush(Color.Black), e.Bounds.X, e.Bounds.Y)
    
    End Sub
    

    End Class

    L 1 Reply Last reply
    0
    • D David Hovey

      Hi there. I need some help with drawing items for a ComboBox Control. For the most part the ComboBox draws just fine. I can scroll up and down and everything is good. The problem is when I drag the scrollbar "thumb" or box to get through the list faster. The items do not display correctly. The ComboBox is set to DropDownList and OwnerDrawVariable. I understand the code below is not very meaningful as I could use the windows implementation to draw the items. The program I'm working on displays certain items in bold, so the code below just illustrates the problem I have. Thanks for your help!!

      Public Class Form1

      Private Sub Button1\_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
      
          Dim i As Integer
      
          For i = 1 To 200
              ComboBox1.Items.Add(i)
          Next
      
      End Sub
      
      Private Sub ComboBox1\_DrawItem(ByVal sender As Object, ByVal e As System.Windows.Forms.DrawItemEventArgs) Handles ComboBox1.DrawItem
      
          If e.Index = -1 Then
              Exit Sub
          End If
      
          e.DrawBackground()
      
          e.Graphics.DrawString(ComboBox1.Items(e.Index).ToString(), e.Font, New SolidBrush(Color.Black), e.Bounds.X, e.Bounds.Y)
      
      End Sub
      

      End Class

      L Offline
      L Offline
      Luc Pattyn
      wrote on last edited by
      #2

      Hi, not sure this will fix it, however it might as your current code is too expensive: for every item drawn you: - create a new SolidBrush - and you don't call Dispose on it, which you should as the class offers such method. It would be better to create a brush once, and keep it handy in a class member so you can reuse it for all items. And actually, you don't even need this as there is a class offering standard brushes, so all you need is Brushes.Black :)

      Luc Pattyn [Forum Guidelines] [My Articles]


      The quality and detail of your question reflects on the effectiveness of the help you are likely to get. Show formatted code inside PRE tags, and give clear symptoms when describing a problem.


      D 1 Reply Last reply
      0
      • L Luc Pattyn

        Hi, not sure this will fix it, however it might as your current code is too expensive: for every item drawn you: - create a new SolidBrush - and you don't call Dispose on it, which you should as the class offers such method. It would be better to create a brush once, and keep it handy in a class member so you can reuse it for all items. And actually, you don't even need this as there is a class offering standard brushes, so all you need is Brushes.Black :)

        Luc Pattyn [Forum Guidelines] [My Articles]


        The quality and detail of your question reflects on the effectiveness of the help you are likely to get. Show formatted code inside PRE tags, and give clear symptoms when describing a problem.


        D Offline
        D Offline
        David Hovey
        wrote on last edited by
        #3

        Thanks for the comment. You remind me to think about that more. New code is below, but issue still exists. I was thinking that perhaps I needed a custom class, that overrides the OnPaint method. This doesn't seem correct as the method would draw the part of the control that doesn't drop down. I searched for quite a while and it doesn't seem anyone else has had this problem.

        Public Class Form1

        Private Sub Button1\_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        
            Dim i As Integer
        
            For i = 1 To 200
                ComboBox1.Items.Add(i)
            Next
        
        End Sub
        
        Private Sub ComboBox1\_DrawItem(ByVal sender As Object, ByVal e As System.Windows.Forms.DrawItemEventArgs) Handles ComboBox1.DrawItem
        
            If e.Index = -1 Then
                Exit Sub
            End If
        
            e.DrawBackground()
        
            e.Graphics.DrawString(ComboBox1.Items(e.Index).ToString(), e.Font, Brushes.Black, e.Bounds.X, e.Bounds.Y)
        
        End Sub
        

        End Class

        L 1 Reply Last reply
        0
        • D David Hovey

          Thanks for the comment. You remind me to think about that more. New code is below, but issue still exists. I was thinking that perhaps I needed a custom class, that overrides the OnPaint method. This doesn't seem correct as the method would draw the part of the control that doesn't drop down. I searched for quite a while and it doesn't seem anyone else has had this problem.

          Public Class Form1

          Private Sub Button1\_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
          
              Dim i As Integer
          
              For i = 1 To 200
                  ComboBox1.Items.Add(i)
              Next
          
          End Sub
          
          Private Sub ComboBox1\_DrawItem(ByVal sender As Object, ByVal e As System.Windows.Forms.DrawItemEventArgs) Handles ComboBox1.DrawItem
          
              If e.Index = -1 Then
                  Exit Sub
              End If
          
              e.DrawBackground()
          
              e.Graphics.DrawString(ComboBox1.Items(e.Index).ToString(), e.Font, Brushes.Black, e.Bounds.X, e.Bounds.Y)
          
          End Sub
          

          End Class

          L Offline
          L Offline
          Luc Pattyn
          wrote on last edited by
          #4

          Hi, I haven't done any ComboBox.DrawItem myself, however I use ListBopx.DrawItem a lot, and they are documented very similarly. Never had any problems. Is your CB double-buffered? is your Form? Mine normally are. You haven't told in any detail what is wrong with the result. here are some suggestions: - if the comboBox.Items are strings, no need to call ToString() - use the entire e.Bounds in DrawString, not just X and Y - if the visual result does not provide a clue, I would add logging code to figure for which items DrawItem gets called/doesn't get called assuming some of the items are not repainted, hence show previous content. BTW: the MSDN example on CB.DrawItem creates and doesn't dispose of its SolidBrush and Font! :)

          Luc Pattyn [Forum Guidelines] [My Articles]


          The quality and detail of your question reflects on the effectiveness of the help you are likely to get. Show formatted code inside PRE tags, and give clear symptoms when describing a problem.


          D 1 Reply Last reply
          0
          • L Luc Pattyn

            Hi, I haven't done any ComboBox.DrawItem myself, however I use ListBopx.DrawItem a lot, and they are documented very similarly. Never had any problems. Is your CB double-buffered? is your Form? Mine normally are. You haven't told in any detail what is wrong with the result. here are some suggestions: - if the comboBox.Items are strings, no need to call ToString() - use the entire e.Bounds in DrawString, not just X and Y - if the visual result does not provide a clue, I would add logging code to figure for which items DrawItem gets called/doesn't get called assuming some of the items are not repainted, hence show previous content. BTW: the MSDN example on CB.DrawItem creates and doesn't dispose of its SolidBrush and Font! :)

            Luc Pattyn [Forum Guidelines] [My Articles]


            The quality and detail of your question reflects on the effectiveness of the help you are likely to get. Show formatted code inside PRE tags, and give clear symptoms when describing a problem.


            D Offline
            D Offline
            David Hovey
            wrote on last edited by
            #5

            Ok. Well here is the info I have. I changed the code quite a bit. Created a custom combobox at runtime. Form and combobox are doublebuffered. It also creates a log file showing index, bounds, and time of DrawItem method being executed. To describe the problem. It would appear that the Background is not being drawn correctly (but this only describes the appearance-I don't think this is the cause). When I quickly scroll the entire list, to the end, the majority of the items appear as a "blob" of black as if all of the items were drawn over top of eachother. The odd thing is this is intermittent. Out of the 20 items shown in the drop down maybe 3 or 4 will be displayed correctly. The log file shows that when quickly dragging through a list, the items are only being drawn on either the last or second to the last visible item bounds. When dragging up the items are only drawn on either the top or second visible item bounds. Since this is the case, internally, either Windows or the .NET framework, would have to be storing the item graphics and then be moving the previous item graphics up or down. But if you click on the scroll bar to get the next or previous "page" all the items will be redrawn from top to bottom... I uploaded the log file to my website http://www.hoveytech.com/drawitemlog.txt Not sure where to go from here. Thanks for your quick answers and continued help!

            Public Class Form1
            Private m_fBold As Font
            Private WithEvents m_cboCustom1 As CustomCombo

            Private Sub m\_cboCustom1\_DrawItem(ByVal sender As Object, ByVal e As System.Windows.Forms.DrawItemEventArgs) Handles m\_cboCustom1.DrawItem
            
                If e.Index = -1 Then
                    Exit Sub
                End If
            
                e.DrawBackground()
            
                If e.Index Mod 4 = 0 Then
                    e.Graphics.DrawString(m\_cboCustom1.Items(e.Index).ToString(), m\_fBold, Brushes.Black, e.Bounds)
                Else
                    e.Graphics.DrawString(m\_cboCustom1.Items(e.Index).ToString(), e.Font, Brushes.Black, e.Bounds)
                End If
            
                LogDrawItem(e.Index, e.State, e.Bounds)
            
            End Sub
            
            Private Sub Form1\_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
            
            
                Me.DoubleBuffered = True
            
                m\_cboCustom1 = New CustomCombo
                m\_cboCustom1.Location = New Point(30, 30)
                m\_cboCustom1.DropDownStyle = ComboBoxStyle.DropDownList
                m\_cboCustom1.DrawMode = DrawMode.OwnerDrawVariable
                m\_cboCustom1.MaxDropDownIte
            
            L 1 Reply Last reply
            0
            • D David Hovey

              Ok. Well here is the info I have. I changed the code quite a bit. Created a custom combobox at runtime. Form and combobox are doublebuffered. It also creates a log file showing index, bounds, and time of DrawItem method being executed. To describe the problem. It would appear that the Background is not being drawn correctly (but this only describes the appearance-I don't think this is the cause). When I quickly scroll the entire list, to the end, the majority of the items appear as a "blob" of black as if all of the items were drawn over top of eachother. The odd thing is this is intermittent. Out of the 20 items shown in the drop down maybe 3 or 4 will be displayed correctly. The log file shows that when quickly dragging through a list, the items are only being drawn on either the last or second to the last visible item bounds. When dragging up the items are only drawn on either the top or second visible item bounds. Since this is the case, internally, either Windows or the .NET framework, would have to be storing the item graphics and then be moving the previous item graphics up or down. But if you click on the scroll bar to get the next or previous "page" all the items will be redrawn from top to bottom... I uploaded the log file to my website http://www.hoveytech.com/drawitemlog.txt Not sure where to go from here. Thanks for your quick answers and continued help!

              Public Class Form1
              Private m_fBold As Font
              Private WithEvents m_cboCustom1 As CustomCombo

              Private Sub m\_cboCustom1\_DrawItem(ByVal sender As Object, ByVal e As System.Windows.Forms.DrawItemEventArgs) Handles m\_cboCustom1.DrawItem
              
                  If e.Index = -1 Then
                      Exit Sub
                  End If
              
                  e.DrawBackground()
              
                  If e.Index Mod 4 = 0 Then
                      e.Graphics.DrawString(m\_cboCustom1.Items(e.Index).ToString(), m\_fBold, Brushes.Black, e.Bounds)
                  Else
                      e.Graphics.DrawString(m\_cboCustom1.Items(e.Index).ToString(), e.Font, Brushes.Black, e.Bounds)
                  End If
              
                  LogDrawItem(e.Index, e.State, e.Bounds)
              
              End Sub
              
              Private Sub Form1\_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
              
              
                  Me.DoubleBuffered = True
              
                  m\_cboCustom1 = New CustomCombo
                  m\_cboCustom1.Location = New Point(30, 30)
                  m\_cboCustom1.DropDownStyle = ComboBoxStyle.DropDownList
                  m\_cboCustom1.DrawMode = DrawMode.OwnerDrawVariable
                  m\_cboCustom1.MaxDropDownIte
              
              L Offline
              L Offline
              Luc Pattyn
              wrote on last edited by
              #6

              Hi David, I noticed you have chosen OwnerDrawVariable, which means each item has its own height, and before DrawItem fires a MeasureItem event gets fired, asking you for the height of the item. Suggestion: - try OwnerDrawFixed; - or provide a MeasureItem handler. With this fixed it works fine for me (also remove the logging in DrawItem for good responsiveness). :)

              Luc Pattyn [Forum Guidelines] [My Articles]


              The quality and detail of your question reflects on the effectiveness of the help you are likely to get. Show formatted code inside PRE tags, and give clear symptoms when describing a problem.


              D 1 Reply Last reply
              0
              • L Luc Pattyn

                Hi David, I noticed you have chosen OwnerDrawVariable, which means each item has its own height, and before DrawItem fires a MeasureItem event gets fired, asking you for the height of the item. Suggestion: - try OwnerDrawFixed; - or provide a MeasureItem handler. With this fixed it works fine for me (also remove the logging in DrawItem for good responsiveness). :)

                Luc Pattyn [Forum Guidelines] [My Articles]


                The quality and detail of your question reflects on the effectiveness of the help you are likely to get. Show formatted code inside PRE tags, and give clear symptoms when describing a problem.


                D Offline
                D Offline
                David Hovey
                wrote on last edited by
                #7

                Thanks for your help! It works now!!

                1 Reply Last reply
                0
                Reply
                • Reply as topic
                Log in to reply
                • Oldest to Newest
                • Newest to Oldest
                • Most Votes


                • Login

                • Don't have an account? Register

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • World
                • Users
                • Groups