Listbox Cell Text Color

I have read the documentation on CellTextPaint but that is an ‘event’ and doesn’t work (I don’t think) the way I need.

What I’m trying to do is to get the row/column from CellClick to tell me what row the user has clicked on, and then redraw the existing black text within that ListBox row to red. The effect being that when the user clicks on a ListBox row the text in that row changes from the default black to red.

If I were to make up my own command to do this it would say something like “Listbox1.Cell(row,column).TextColor = &cFF0000” and I would place it in the CellClick event for the listbox.

Is there a way to do this?

Use the ListBox.Selected property in the CellTextPaint event to detect whether the cell being painted belongs to a currently selected row:

Event CellTextPaint(g As Graphics, row As Integer, column As Integer, x as Integer, y as Integer) As Boolean If Me.Selected(row) Then // draw the text yourself g.ForeColor = &cFF000000 g.DrawString(Me.Cell(row, column), x, y) Return True Else Return False End If End Function

If you want to do this with a row that isn’t selected (but was clicked on) then you’d need to store the row number from the click event and then retrieve it in the CellTextPaint event.

The Selected works when the row is selected but not specifically the cell in the row that is selected.

Store the Row and Column parameters from the CellClick event (e.g. as properties of the window) and then compare them to the Row and Column parameters of the CellTextPaint event.

I guess I could just try it, but if a row is already selected (because a different cell on that row was already clicked) I am not sure CellTextPaint would fire on all platforms as in normal operation nothing would need to be repainted .

And even if it works now, it might not in the future if more drawing optimization is ever done on the listbox.

To be sure in the cell is aways redrawn in CellClick I would would do:

If me.Selected(row) Then ' A cell in that row was already clicked on

   If  LastRow = row And LastColumn = column Then Return False ' Same as last Cell  clicked on

   me.InvalidateCell(row,column)  ' Make sure selected cell always gets redrawn
   me.InvalidateCell(LastRow, LastColumn)  ' Make sure the prior cell selected always gets redrawn

End if

LastRow = row
LastColumn = column

Also In CellTextPaint I would let the framework draw the text and just set the color:

If row = LastRow  And column = LastColumn And  Me.Selected(row) Then
    g.ForeColor = &cFF000000
End If

Andrew’s method works very nicely … It colors the row that was clicked perfectly. But when you click another row the previously clicked row reverts back to black text.

I forgot to give one more parameter.

I would like for the rows that have been clicked to remain red to tell the user which rows have been clicked on so far.

Is there a way to do that?

[quote=434018:@Marc Speth]Andrew’s method works very nicely … It colors the row that was clicked perfectly. But when you click another row the previously clicked row reverts back to black text.

I forgot to give one more parameter.

I would like for the rows that have been clicked to remain red to tell the user which rows have been clicked on so far.

Is there a way to do that?[/quote]

Retain a list of previously clicked rows either in an array or a dictionary.

… and implement that list how? … in what event?

Sorry if this sound harsh but it’s IMO it’s true…
Given everything in this the thread, you should be able to figure that out yourself. Giving you more specifics at this point will hurt you more than help you in the long run.

  • karen

I have tried to change the cell text color for a range of cells inside CellClick event. But where the CellTextPaint event passes g, the graphics object, to you, as well as Row, Column, X, and Y, the CellClick event doesn’t. Therefore I have to supply these myself.

Row and Column are easy. X and Y I can guess from the experiments I did in the CellTextPaint event. But so far I have not been successful at getting the graphics object for the ListBox, or perhaps the Cell.

Even if I put Dim ‘g As Graphics’ at the beginning of the CellClick event, when it tries to execute the:
g.ForeColor = &cFF000000
g.DrawString(Me.Cell(row, column), x, y)
… commands I get the Nil Object error because I don’t know how to get the graphics property of the ListBox, or Cell, or perhaps Row to be passed to those command lines.

I have also tried forcing a Select for a row in software, thereby forcing a redraw of that row, thereby triggering a text recolor for that row in CellTextPaint. But so far it appears that Select is can only be ‘passed’ and not ‘forced’.

You need to treat the events as completely separate. In CellClick, you record the row/column and then invalidate the listbox. That causes the CellTextPaint events to fire. In CellTextPaint, you check each cell against your list of cells and set the color accordingly. There are many ways to store the row/column of the clicks. Tell us what you have tried, and we can guide you from there.

In cellClick you can add the row to a list property in the window ClickedRows(-1) as integer then call invalidateCell(row,column) to cause it to repaint.

In the celltextPaint, check the list for the row.
If ClickedRows.indexof(Row) > -1 then g.forecolor=&cff0000

You can’t access the Graphics property of a control, except as it is passed to you in an event.

Thank you Tim and Jim.

That was what I needed to know to get it working as desired.

Thank you!!!
Thank you!!!
Thank you!!!

I didn’t know before that “InvalidateCell” would force a repaint.

In fact, before this discussion I didn’t know that InvalidateCell even existed.

I first started programming in 1978 in the days of Fortran and BASIC linear programming. So wrapping my head around the concept Objects, Inheritance, and Events has proven to be a significant challenge for me.

I come from the days when if you wanted something to be displayed on the screen you typed '10 PRINT “This is what I want on the screen.” And if you wanted to erase it you used VTAB and HTAB to get back to that position on the screen and then issued a '30 PRINT " " ’ to print blank spaces over it. There was no ‘canvas’ and graphics properties that you had to DRAW into.

So this has been an uphill battle for me to retrain my brain.

And again, I thank you for your help.

Darn! I wanted to give both Tim AND Jim credit for solving my problem because it was the combined information from both posts that led me to the solution.

But the system will only let me click on one “this solved my problem”.

Go to the ListBox documentation and read the docs about each event, property, and method. I had to do that a few times but eventually it stuck (or some of it did, anyway).