Display error in Canvas in newer releases

Hi everyone,
several days ago i was moving from Xojo release 2019 1.1 to the latest release.

In one of my projects everything seems to work fine in the new release but i’ve got one problem with canvases.

In each window I’m displaying a title painted on a canvas and a ‘NEU’-button, a canvas as well. In the older release it was displayed correctly like this:
2021-05-10 18_36_59-COMETA ERP V.2.0.18 _ Cometa Test _ Kai

The same code in the latest release shows the canvas like this:
2021-05-10 18_36_32-COMETA ERP V.2.0.18 _ Cometa Test _ Kai

But when i activate the window with the canvas a second thime everything ist displayed correctly.

Here is my code in the paint event of the ‘title’-canvas:

g.ForeColor=StyleApp.titleColor
g.TextFont=StyleApp.titleFont
g.TextSize=StyleApp.titleSize

Dim s As String
s=“Aufträge”
If len(s)>0 Then
g.DrawString(s,0,(g.Height/2)+(g.TextAscent/2)-2)
End If
Me.Width=g.StringWidth(s)+5
Me.Invalidate
canPlus.Left=Me.Left+Me.Width+10
canPlus.invalidate

I tried in other releases newer than 2019 1.1 as well, having the same problems.

Do i have to do something different with displaying canvases in the newer releases?

First off i think it may be better to remove the (me.)invalidate inside the paint event, it will cause a redraw loop probably.

You might want to check the new API 2.0 functions and move to those, so g.DrawString becomes g.DrawText etc. These are probably more tested in xojo 2021+ versions.

g.DrawingColor = StyleApp.titleColor
g.FontName = StyleApp.titleFont // Set to the font name as string
g.FontSize = StyleApp.titleSize

Dim s As String = "Aufträge"
If len(s)>0 Then
    g.DrawText(s,0,(g.Height/2)+(g.FontAscent/2)-2)
End If
Me.Width=g.TextWidth(s)+5
Me.Invalidate // <-- are you sure this is needed in the paint event?
canPlus.Left=Me.Left+Me.Width+10
canPlus.invalidate

That would probably do it.

Thanks Derk,
i just updated to the new API 2.0 functions but still have the same problem. I also tried it with me.invalidate inside the Paint event and without the invalidate. The buttons and titles are only displayed correctly when i refresh the window e. g. resize or reactivate.

Remove this code from the Paint event and calculate the values outside the event/before the event is fired. Paint is for drawing only. Never invalidate here.

Did you try to re-layer the canvasses? In the ide press the canvas then tlthe icons to “bring to front”
See if that helps.

No, still the same problem

it seems like you have 2 (or more) squares being cleared. Do you happen to use InvalidateRect (api1 method) or invalidate(x, y, w, h) ?

Or do you happen to use the backdrop?

Carsten, this may be a solution, but how can i calculate the width of the string which is inside the paint event from the outside? This button needs a variable string because im displaying it with different content depending on the language and other parameters.

It is strange to draw in the canvas and change its size after.
By doing that, if the size is increased, you have to wait the next refresh to have the right drawing.

Yes, this makes sense. So i have to overthink my concept.

Create a temp picture 1 x 1 pixels and use it’s Graphics with the same values (font name, size etc.) to calculate string width and others. Store these values in properties and set the size and position of the canvases. Use the properties also in the Paint event.

I made a sample test with a canvas and a button.

In the Canvas paint event :

Dim s as String = “Very_very_long_string”
System.DebugLog(Me.Width.ToText) //=> 60 the first time
Me.Width = g.TextWidth(s)+5
System.DebugLog(Me.Width.ToText) //=> 125
g.DrawText(s, 0, (g.Height/2)+(g.FontAscent/2)-2)

The text is not displayed correctly.
In the action event of the button :

Canvas1.Invalidate

A click on the button and the text is displayed correctly.

Canvas1.Invalidate in the Activate event of the window solves also the problem.

Changing the dimensions of the control during its paint event is not a good idea.

3 Likes

Absolutely. When you change the Canvas’s size during the paint event, you are invalidating it by that. Move all resizing and invalidating out of the paint event.

you could subclass this canvas and use a computed property for the text/caption.