Here are three examples from our own Xojo made applications on what you can do with the Listbox.CellTextPaint event:
The first one takes the text from the cell and reduces text size until the text fits or we are down to 8 point font size. This is useful if you for example display a postal address in a 40 pixel height row Listbox. As we don't know how long an address is, we scale it down. So a 2 line one shows in a bigger font than a 4 line one.
The font is set by the listbox properties including any italic, bold or underline flag.
EventHandler Function CellTextPaint(g As Graphics, row As Integer, column As Integer, x as Integer, y as Integer) As Boolean dim s as string = me.Cell(row, column) g.TextSize = 13 dim h as integer = g.StringHeight(s, g.Width) while h > g.height and g.textsize > 8 g.textsize = g.textsize - 1 h = g.StringHeight(s, g.Width-4) wend g.DrawString s, 2, g.textsize, g.Width-2 Return true End EventHandler
The following examples is a bit more complex. First we store in the rowTag a boolean flag for whether the record is old. Normally we would store our record ID for database records in the RowTag or an object of a data class. In that case each row represents two records, so we have those record IDs in cellTags. Now a line with boolean flag set is drawn in red. Other entries are checking whether the date in the celltag is older than today. Old entries are shown in gray. All other unselected rows will be drawn in black. Lines left are drawn in default color. It is important to keep default color for selected lines to make sure you have the right text color on the highlighted rows.
You may notice that we don't draw any text here ourselves. That is because we return false and let the Listbox class draw the text using our color.
EventHandler Function CellTextPaint(g As Graphics, row As Integer, column As Integer, x as Integer, y as Integer) As Boolean dim useRedColor as Boolean = me.CellTag(row, 0) if useRedColor then g.ForeColor = &cFF0000 return false end if dim d as date = keys.CellTag(row, 1) if d <> nil then static today as new date if d.TotalSeconds < today.TotalSeconds then // expired in gray g.ForeColor = &c888888 Return false end if end if if row <> me.ListIndex then // all non selected rows in black text please g.ForeColor = &c000000 end if End EventHandlerThe third example kind of merges both. So if the row is marked as gold, we switch to gray color.
Below that we use different text sizes depending of the number of lines we show. And we draw here our text outsells, so it can wrap nicely. For that we use 2 for the left coordinate and g.width-2 as wrap width, so we leave two pixel to the left. This looks nicer than drawing at 0 offset.
EventHandler Function CellTextPaint(g As Graphics, row As Integer, column As Integer, x as Integer, y as Integer) As Boolean // lines marked old are in gray dim isOld as Boolean = me.RowTag(row) if isOld then g.ForeColor = rgb(179,179,179) else g.ForeColor = &c000000 end if // use different text sizes for differnet number of lines dim s as string = me.Cell(row, column) dim h as integer = g.TextSize dim c as integer = CountFields(s, EndOfLine) if c > 3 then g.TextSize = 8 g.DrawString s, 2, 8, g.Width-2 g.TextSize = h elseif c = 3 then g.TextSize = 10 g.DrawString s, 2, 10, g.Width-2 g.TextSize = h else g.DrawString s, 2, 13, g.Width-2 end if Return true End EventHandlerI hope this helps you to leverage Listbox.CellTextPaint event better. Comments?