First, at least back when I was writing the mergeable Listbox class ~9 years go, I found when the highlight color was painted depended on platform and was different between Mac and Windows. In one case the highlight was drawn before CellBackgroundPaint was called and the other after, but before CellTextPaint. I don’t recall which was platform did what.
As for the rest, in the general case it is a good idea to use CellTextPaint as the text area accounts for the presence of RowPictures, Checkboxes and hierarchical indents.
If you use CellBackgroundPaint for the content, you have to worry about all of that yourself.
Never call Refresh. It forces an immediate synchronous redraw of the entire ListBox.
Use InvalidateCell whenever possible. ListBox tries to redraw only the cells that are dirty, so Invalidate versus InvalidateCell can mean the difference between hundreds of cells redrawing and a handful. Note that changing a cell’s contents automatically invokes InvalidateCell, so it’s not necessary unless you’re doing things ListBox doesn’t know about.
If you really need every single cell in the ListBox redrawn, use Invalidate and pass in False for the ‘eraseBackground’ parameter.
And some minor ListBox performance tips if you find your ListBox is being slow:
Avoid using gridlines unless you really need them.
Avoid customizing the background painting unless you really need to. Implementing the CellBackgroundPaint event requires ListBox to draw backgrounds a single cell at a time instead of an entire row at a time. This isn’t to say that you should never use CellBackgroundPaint, just that you should think about whether or not the custom look you’re going for is worth it.
that you should let the listbox draw the way it draws unless there is some ultra important reason to override how it draws because overriding cell background paint can slow drawing down significantly.
instead of drawing one large rectangle that is all visible cell backgrounds it has to call each cell background paint method for each cells background.