Text colour in a listbox row

I have a listbox with rows in it and my own rules about highlighting when a row is clicked. So for example after clicking a row to select it, another click in that row will deselect it. This is where the difficulty arises: the row is clicked and in CellBackgroundPaint I set the ForeColor to my highlight colour. Clicking again sets it to white again (I keep my own dictionary of which rows the user has selected).

But, on clicking the row, when adding my highlight colour the text colour gets set to white. I really don’t want this: I will choose a highlight colour to provide good contrast with the black text. So then, when the row is clicked a second time the ForeColor is set to white and the text, being the same colour, disappears.

How do I stop this fiddling with the text colour? I return true from CellBackgroundPaint.

And apropos of CellBackgroundPaint, the docs could be clearer. It says that this event is triggered for “row every row”. But when is it triggered. I see nothing about that.

cellTEXTpaint event is what you want… this draws the TEXT, background event draws the background

I don’t want to draw the text; I already have that. I want to paint the background of the cell without it altering the colour of the text already in the cell.

But you can use that event to force the color of the text. You don’t have to draw the text yourself, just set g.ForeColor to black in that event and return False.

One difference is, if text in the ListBox cell is too long to fit, the ellipsis will show like:

|Tim Strea…|

But if you use Drawstring in the CellTextPaint event, it will draw as much as it can fit in the cell then truncate it. I prefer that to all those ellipsis all over the place. There may be options to override the behavior, but that is how it works out of the box.

The cell is drawn in 2 parts: the background color and then the text. Each has its own event associated with it. Additionally,
the cell is drawn differently based on whether it is Selected or not. If the cell is selected, then the background is drawn in blue and the text is drawn in white. If you want to draw it differently, you have to override both independent of each other. Ie., you have to implement both CellBackgroundPaint and CellTextPaint.

As Kem mentioned, you don’t have to actually draw the text yourself. Just set g.ForeColor.

CellBackgroundPaint

g.forecolor=&C00FF00 // green
g.fillrect 0,0,g.width,g.height
return true

CellTextPaint

g.forecolor=&cff0000 // red 
return false // or omit this entirely

This will draw RED text on a GREEN background

[quote=273370:@Dave S]CellBackgroundPaint

g.forecolor=&C00FF00 // green
g.fillrect 0,0,g.width,g.height
return true

CellTextPaint

g.forecolor=&cff0000 // red 
return false // or omit this entirely

This will draw RED text on a GREEN background[/quote]

Thanks, that looks a lot better. Although I would describe it as colouring the text rather than drawing it.

Thanks, this is a useful explanation that it would be good to see in the documentation.

However, it is still unclear just when these events occur. When the cell is given a value is one occasion, but now it seems that clicking and other actions do so too. This seems rather wasteful, since I already have the click event. Further, at least for CellBackgroundPaint, it’s called for every visible row and column, which is even more wasteful as for most of these, no action is needed.

The events occur whenever the cell is painted (drawn on screen) as the name implies.
Change the text? Paint.
Change selection? Paint.
Scroll? Paint.
Move? Paint.
Resize? Paint.
There are many times it has to be redrawn, and it can be even more frequent than that. Additionally you can force repainting with Refresh, and request painting with Invalidate.

It can be wasteful if you do a lot of calculation in the Paint event, but in most cases it’s not an issue (it’s happening whether you use the events or not.) We have access to these events because Listbox is not a system native control, but rather a custom control created by Xojo.