Re: Owner drawn listbox

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance

From: Kevin Aubuchon (kevin.aubuchon_at_sbcglobal.net)
Date: 08/06/04


Date: Fri, 06 Aug 2004 02:19:06 GMT

Here is a class (OwnerDrawListBox) I wrote that puts items in a listbox with
the option of a bold font. Pass a reference of the listbox to the
OwnerDrawListBox object, and use the objects Add method for adding items to
the Listbox. Obviously the value of this example is how to implement
drawItem() and measureItem(). I think that's the cause of your problem.
Modify the class to implement your logic.

HTH,
kevin aubuchon

Imports System.Windows.Forms
Imports System.Drawing
Imports System.Drawing.Text

Public Class OwnerDrawListBox
    '
    ' Kevin Aubuchon 5/6/2004
    '
    '

    ' Utility class to handle owner draw listboxes. Individual line items
    ' may be drawn with different fonts, colors, etc.
    '
    ' Currently if a row is 'special', then the current font is
    ' used but made bold. Add implementation as needed for more
    ' exotic treatment (different background colors, etc.)
    '
    Private lb As ListBox
    Private bBold As Boolean = True
    Private boldFont As Font
    '
    ' helper class to hold 'special' status
    '
    Class helper
        Inherits Object
        Dim txt As String
        Friend special As Boolean
        Sub New(ByVal s As String, ByVal sp As Boolean)
            txt = s
            special = sp
        End Sub
        Public Overrides Function ToString() As String
            Return txt
        End Function
    End Class

    Public Sub New(ByVal theListBox As ListBox)
        If IsNothing(theListBox) Then Throw New
NullReferenceException("ListBox object empty")
        lb = theListBox
        boldFont = New System.Drawing.Font(lb.Parent.Font, FontStyle.Bold)
        lb.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawVariable
        AddHandler lb.DrawItem, AddressOf drawItem
        AddHandler lb.MeasureItem, AddressOf measureItem

    End Sub
    Public Property UseBoldFont() As Boolean
        Get
            Return bBold
        End Get
        Set(ByVal Value As Boolean)
            bBold = Value
        End Set
    End Property
    Public Sub Add(ByVal s As String, ByVal special As Boolean)
        lb.Items.Add(New helper(s, special))
    End Sub
    Public Sub Clear()
        lb.Items.Clear()
    End Sub
    Private Sub drawItem(ByVal sender As Object, ByVal e As
DrawItemEventArgs)
        Dim brush As Brush

        ' The following method should generally be called before drawing.
        ' It is actually superfluous here, since the subsequent drawing
        ' will completely cover the area of interest.
        e.DrawBackground()

  If e.Index < 0 OrElse e.Index > Me.lb.Items.Count - 1 Then Exit Sub

        'The system provides the context
        'into which the owner custom-draws the required graphics.
        'The context into which to draw is e.graphics.
        'The index of the item to be painted is e.Index.
        'The painting should be done into the area described by e.Bounds.

        brush = Brushes.White
        e.Graphics.FillRectangle(brush, e.Bounds)

        Dim f As Font
        Dim h As helper = CType(lb.Items.Item(e.Index), helper)
        If Not IsNothing(h) AndAlso h.special Then
            f = boldFont
        Else
            f = lb.Parent.Font
        End If

        e.Graphics.DrawString(h.ToString(), f, Brushes.Black, e.Bounds.X,
e.Bounds.Y)

    End Sub

    'Return the height of the item to be drawn
    Private Sub measureItem(ByVal sender As Object, ByVal e As
MeasureItemEventArgs)
        Dim displayText As String
        Dim stringSize As SizeF

 If e.Index < 0 OrElse e.Index > Me.lb.Items.Count - 1 Then Exit Sub

        'Work out what the text will be
        Dim h As helper = CType(lb.Items.Item(e.Index), helper)
        displayText = h.ToString()

        'Get width & height of string
        stringSize = e.Graphics.MeasureString(displayText, lb.Parent.Font)

        'Account for top margin
        stringSize.Height += 3
        e.ItemHeight = CInt(stringSize.Height)
    End Sub
End Class

"Patty O'Dors" <PattyODors@discussions.microsoft.com> wrote in message
news:E76205AC-3633-478E-A0A3-BB20F3737CFA@microsoft.com...
> Hi
> I have some code to create an ownerdrawn listbox (derived), and when I add
> an item to it, the bold text of the first item (the title, 'Collections
and
> Maturities') mysteriously seems to get bunched up at the right, i.e.
squashed
> up! any idea why?
>
> The main bit of the code is as such
> // (in progressReporter.cs)
>
> protected struct LBRow //a row of the listbox, whether it be the title or
a
> table listing
> {
> public string Text;
> public int Rows;
> public bool IsTitle;
> public LBRow(string text, int rows, bool istitle)
> {
> Text = text;
> Rows = rows;
> IsTitle = istitle;
> }
> }
>
> public void AddReport(ProgressReport p)
> {
> Items.Add(new LBRow(p.JobName, 0, true));
> foreach(ProgressReport.ProgressReportItem pi in p.TablesCopied)
> Items.Add(new LBRow(pi.TableName, pi.Rows, false));
> }
>
> public struct ProgressReport
> {
> public string JobName;
> public ProgressReportItem[] TablesCopied;
> public struct ProgressReportItem
> {
> public string TableName;
> public int Rows;
> public ProgressReportItem(string tablename, int rows)
> {
> TableName = tablename;
> Rows = rows;
> }
> }
> public ProgressReport(string jobname, params ProgressReportItem[]
> tablescopied)
> {
> JobName = jobname;
> TablesCopied = tablescopied;
> }
> }
>
>
> // (in frmMain)
>
> private void Form1_Load(object sender, System.EventArgs e)
> {
> listBox2.AddReport(new ProgressReporter.ProgressReport(
> "Collections and Maturities",
> new ProgressReporter.ProgressReport.ProgressReportItem("Table1", 100000),
> new ProgressReporter.ProgressReport.ProgressReportItem("Table2",
500000)));
> }



Relevant Pages

  • Re: Listbox selectedindex changed event not firing from within datagrid
    ... the listbox to the command button. ... Private Sub DataGrid1_ItemCreated(ByVal sender As Object, ... >> Although you have added SelectedIndexChanged event handler for ListBox, ...
    (microsoft.public.dotnet.framework.aspnet.datagridcontrol)
  • RE: VBA : how to concatene a list of mails from a form
    ... "PHil" wrote: ... now the button is in the top of the sub form, maybe I should put in the main ... provides your list of students for the lesson. ... The code you have is for a listbox, it loops through and checks which items ...
    (microsoft.public.access.modulesdaovba)
  • Re: Reading a colormap?
    ... " Filter - brings up a filter dialog for the color names", ... # Make a scale for each color component. ... # Make a listbox full of color names. ... sub makeRGBAScales ...
    (comp.lang.perl.tk)
  • RE: Cannot get code to work for API Save Dialog Box
    ... The listbox is called listname so that should not be the problem. ... Private Sub cmdExportSupportSchedule_Click ... Dim strFilter As String ... Dim varGetFileName as Variant ...
    (microsoft.public.access.forms)
  • RE: Cannot get code to work for API Save Dialog Box
    ... I assume that you are not really naming your listbox listbox. ... Private Sub cmdExportSupportSchedule_Click ... Dim strFilter As String ... Dim varGetFileName as Variant ...
    (microsoft.public.access.forms)