Common reasons for cellbackgroundpaint to not work?

Having a blockade here with cellbackgroundpaint in a listbox which I suspect my be some simple thing I’m overlooking.

2016r4.1 on OSX.

I have a listbox which paints the cell background white and paints a circle in the middle of the cell (well actually a circle with a with the same as the g.width and the defaultrowheight always equals the column width.

celltextpaint then places the cell contents in white over the circle.

Anyhow, I’ve a got a problem where when the window loses focus to another app and them come back, the cellbacground is not painting. When I then click on the listbox, the row clicked shows up and I also have a container control that shows more detail of the cell’s content on mousemove. As this container control goes around the “white list box” what it passes over gets painted.

Wher can I sart to figure out why this is happening?

EDIT: I’m narrowing it down to one method (I’ve three that paint different things.) The problem occurs when the listbox is taller than the number of rows it has. In addition, while active and patined corectly, if I click in the lower part of the listbox where there are no real rows, the last active row goes blank and the container control begins erasing as it moves about.

Try invalidating the canvas in the Window.Activate event to see if that alleviates the problem at all.

No canvas, but I tried listbox1.invalidate and it does not solve the issue, unfortunately.

Sorry, million things going on, you got what I meant though. Not much more advice I can give without looking into the drawing code, it sounds from your edit that you’ve got some odd drawing issues.

Yeah, I was kind of hoping there was a general “oh, really you should pay attention to this when drawing in cells”, but it looks like I’ll have to dig deeper. Thanks.

Let us know if you find a solution, I ran into this about a year ago and never was able to puzzle out what combination of row count, column count, column widths, and row heights caused the problem. I also found that having the listbox do it’s own horizontal scrolling was one of the things that made it go wonky.

Did you assign a value to ‘ListBox.DefaultRowHeight’ and ‘ListBox.TextSize’?

It seems I had this trouble in an earlier version, but fixed it with what I knew was a “workaround” but now 20 or so versions later, I must have reintroduced it.

This is the code in my method for painting. It is one of three ways to paint and is called from cellbackgroundpaint using a select case on a window property to choose it.

The method params are: g as Graphics, row as integer, column as integer, lb as listbox

[code] dim s as string = lb.celltag(row,column)
//The cell tag contains a string we split to get an
//“A,B,C, etc used in the ValueColor method to set the color according to the letter. txt does the //same, but for a different type of value.
dim v as string
dim txt as string
if s <> “” Then
Dim sV(-1) as string
sV = s.Split(”:")
v = sV(0)
txt = left(sV(1),1)
end

	g.ForeColor = &cFFFFFF00
	
	g.FillRect(0,0,g.Width,g.Height)//paint the cell white
	if lb.ListIndex <> -1 Then
			dim d as integer = lb.DefaultRowHeight-4
			dim w as integer = lb.Width/lb.ColumnCount
			if Apparatus <> "VT" Then
					g.ForeColor = Valuecolor(v)
			else
					g.ForeColor = vaultcolor(txt)
			end if
			if lb.CellTag(row,column) <> Nil Then
					g.FillOval((w/2)-(d/2),3,d,d)//draw the circle
			else
			end
	end
	[/code] 

EDIT TO ADD: This is called in the cellbackgroundpaint event before thi method to avoid an exception, because when you get beyond the available row count there are no cell tags which are needed to run the paint method. Maybe this should be moved into the above method somehow?

if row > me.ListCount-1 Then return True end

This could be the problem, but I don’t think so as another method uses the same idae and has no issues.

In short, I’m selecting from a database and getting the total number of records. Then, the user has a slider to magnify or shrink the size of the circles and that sets the number of columns. Then the width of the listbox is calculated, divided by the needed number of columns and that number is used to set the defaultrowhieght and textsize. There are no issues drawing the listbox altogether, it just goes wonky when the window loses focus and gets activated again or when the user clicks in the listbox below the actual rows (when the listbox is higher than the number of rows).

There doesn’t seem to be a problems when the listbox has more rows than height.

Where is InvalidateCell that triggers this event ? Have you placed a System.Debuglog() in this code to see if it executes at all ?

I’ve not found a place to put invalidatecell. the method is called from cellbackgroundpaint, so i don’t know where i would put it elsewhere. I’ve tried a few places, but nothing helps.

as far as using th debugger, i placed it at the end of the method and it is getting called when needed. I specially set the recordset so only one row would fill and when first run it shows fine and the debugger shows the method executes wher it should. But when I click below the rows, but in the listbox, the listboxes listindex row goes white, but the debugger shows drawing taking place.

I would think it has to do with the listindex then, but still when activating the window all the rows - everything - goes white and that seems indepedent of the listindex.

Here are all the steps to a small project with the issues:

Create a window (wMain) with a listbox (lbChart), slider1 and slider2 and label1 and label2

lbChart.CellBackgroundPaint

if row > me.ListCount-1 Then return True end dim s as string = me.celltag(row,column) g.ForeColor = &cFFFFFF00 g.FillRect(0,0,g.Width,g.Height) if me.ListIndex <> -1 Then dim d as integer = me.DefaultRowHeight-4 dim w as integer = me.Width/me.ColumnCount g.ForeColor = Valuecolor(s) if me.CellTag(row,column) <> Nil Then g.FillOval((w/2)-(d/2),3,d,d) else end end system.DebugLog("Row: "+str(row)+" - Column: "+str(column)+ " - Value: " + s) Return True

and

lbChart.CellTextPaint

g.ForeColor = &cFFFFFF00

Slider1 - minimun 5 / value 55 / maximum 900
Slider1.valueChanged:

label1.Text = "Number of cells: "+str(me.Value) updatelb(lbChart)

Slider2 - minimun 20 / value 50 / maximum 720
Slider2.valueChanged:

label2.Text = "Size of cells: "+str(me.Value) updatelb(lbChart)

also call updatelb(lbChart) for wMain open, resized

The two methods in the window:

[code]Public Sub updatelb(lb as listbox)
Dim cellcontent() as string = Array(“A”,“B”,“C”,“D”,“E”,“F”,“G”,“H”,“I”)
Dim r As New Random
Dim j,i,w As Integer
Dim cellWidth as integer
cellWidth = Slider2.Value
w = wMain.Width
dim theCount as Integer = slider1.Value
dim xCols as integer
dim xRows as integer
xCols = w/cellWidth
xRows = floor(theCount/xCols)+1

dim row,column as Integer
row = 0
column = 0
lb.DeleteAllRows
lb.ColumnCount = xCols
lb.DefaultRowHeight = cellWidth
lb.TextSize = cellWidth/3
lb.AddRow “”

for i = 0 to theCount-1
j = r.InRange(0, cellcontent.Ubound)
lb.CellTag(row,column) = cellcontent(j)
lb.cell(row,column) = cellcontent(j)
lb.CellAlignment(row,column) = Listbox.AlignCenter

if column < lb.ColumnCount-1 Then
  column = column +1
else
  column = 0
  lb.addrow ""
  row = lb.LastIndex
end if

Next
lb.ListIndex = 0

End Sub

[/code]

And this one for setting the colors for the circles to draw:

Public Function Valuecolor(v as String) as color Dim c as color if v = "A" Then c = &c00A24C00 elseif v = "B" Then c = &c00A29C00 elseif v = "C" Then c = &c4C00A200 elseif v = "D" Then c = &c9D00A200 elseif v = "E" Then c = &cA24C0000 elseif v = "F" Then c = &cA29D0000 elseif v = "G" Then c = &c09DAA500 elseif v = "H" Then c = &c2732CC00 elseif v = "I" Then c = &cA0005400 else c = &cFFFFFF00 end if return c End Function

I strongly suspect the reason why it does not paint is one of your conditions. I would remove them, verify it actually paints, then reinstate them one by one until the bug appears.

//if row > me.ListCount-1 Then // return True //end dim s as string = me.celltag(row,column) g.ForeColor = &cFFFFFF00 g.FillRect(0,0,g.Width,g.Height) //if me.ListIndex <> -1 Then dim d as integer = me.DefaultRowHeight-4 dim w as integer = me.Width/me.ColumnCount g.ForeColor = Valuecolor(s) //if me.CellTag(row,column) <> Nil Then g.FillOval((w/2)-(d/2),3,d,d) //else //end //end system.DebugLog("Row: "+str(row)+" - Column: "+str(column)+ " - Value: " + s) Return True

This should definitely filloval. Then when you reinstate your conditions, you should bump into the one that prevents paint.

@Michel Bujardet Thank you very much. It seems to be the condition “if if me.ListIndex <> -1 Then” which makes sense, I think.

It’s late, and I’ll check thoroughly in the morning, but I think that is the problem.