Imports System.Windows.Forms
Imports System.Drawing

Public Class ListBoxEx : Inherits ListBox

    Public Sub New()
        MyBase.New()
        DrawMode = Windows.Forms.DrawMode.OwnerDrawVariable
        AddHandler Application.Idle, AddressOf Application_Idle
    End Sub

    Private ReadOnly Property ItemTextFormat() As StringFormat
        Get
            Static sf As StringFormat
            If sf Is Nothing Then
                sf = New StringFormat(StringFormatFlags.LineLimit)
                sf.Trimming = StringTrimming.Character
            End If
            Return sf
        End Get
    End Property

    Protected Overrides Sub OnMeasureItem(ByVal e As System.Windows.Forms.MeasureItemEventArgs)
        If Items.Count < 1 Then Return

        Dim item = Items(e.Index)
        If item Is Nothing Then item = ""
        e.ItemHeight = CInt(e.Graphics.MeasureString(item.ToString, Font, ClientSize.Width, ItemTextFormat).Height)
    End Sub

    Protected Overrides Sub OnDrawItem(ByVal e As System.Windows.Forms.DrawItemEventArgs)
        If Items.Count < 1 Then Return

        e.DrawBackground()
        Using br As New SolidBrush(e.ForeColor)
            Dim item = Items(e.Index)
            If item IsNot Nothing Then
                e.Graphics.DrawString(item.ToString, Font, br, e.Bounds, ItemTextFormat)
            End If
        End Using
        e.DrawFocusRectangle()

    End Sub

    Protected Overrides Sub OnClientSizeChanged(ByVal e As System.EventArgs)
        MyBase.OnClientSizeChanged(e)
        remeasuresItems = True
    End Sub

    Private remeasuresItems As Boolean = False

    Private Sub Application_Idle(ByVal sender As Object, ByVal e As EventArgs)
        If Not remeasuresItems Then Return
        RemeasureItems()
        remeasuresItems = False
    End Sub

    Private Sub RemeasureItems()
        DrawMode = Windows.Forms.DrawMode.Normal
        DrawMode = Windows.Forms.DrawMode.OwnerDrawVariable
    End Sub

End Class
