Make one.
//property of window
pictBuffer as picture
pictBuffer = new picture (canvas.width, canvas.height)
//(you need to recreate that if the canvas size changes)
But from the g property of the canvas I want to generate the picture.
Maybe is not possible?
Thats correct.
G does not contain a picture for you to save.
Xojo should not crash using SavefileDialog on the paint event, event is it is not a good place to call it.
I understand that is not possible, with Xojo, to recreate a picture from a Graphics. So if saving is needed should be used a buffer.
Two canvas show the same
FIRST CANVAS
Sub Paint(g As Graphics, areas() As REALbasic.Rect) Handles Paint
g.DrawRectangle(0,0,me.Width,me.Height)
g.FontName = "Arial"
g.FontSize = 20
g.DrawingColor = Color.Blue
g.DrawText("Hello!", 40, 40)
End Sub
SECOND CANVAS
Sub Paint(g As Graphics, areas() As REALbasic.Rect) Handles Paint
pictBuffer = new picture(400,400)
var pBG as Graphics = pictBuffer.Graphics
pBG.DrawRectangle(0,0,me.Width,me.Height)
pBG.FontName = "Arial"
pBG.FontSize = 20
pBG.DrawingColor = Color.Blue
pBG.DrawText("Hello! with buffer", 40, 40)
g.DrawPicture(pictBuffer,0,0)
// Now, pictBuffer contain the image showed
// and may be saved.
End Sub
you could use the backdrop property as buffer.
in canvas open use
Sub Open() Handles Open
Me.Backdrop = New Picture(Me.Width, Me.Height)
End Sub
if you paint use this
Sub Action() Handles Action
Var pic As Picture = Canvas1.Backdrop
Var r As New Random
pic.Graphics.DrawingColor = Color.Red
pic.Graphics.FillOval(r.InRange(32,128),r.InRange(32,128),r.InRange(24,32),r.InRange(24,32))
Canvas1.Invalidate(False)
End Sub
try if you get canvas backdrop 1:1 to store as image file
Xojo may not actually be crashing, the application may be terminated by the OS for blocking windowServer. The contents of the crash report would confirm.
This design is making the OS wait for the content of the view, which maybe holding up a draw of the window, or even the entire screen. While at the same time, this design is asking the OS to draw another window atop the current window, which may be incurring additional redraws of a window that contains a view which is blocking a draw.
Even if the application was still running, it would impact system performance in a negative way.
You could always try creating a offscreen bitmap and using rectControl.drawInto to draw the canvas contents into the offscreen bitmap.
Sub Paint(g As Graphics, areas() As REALbasic.Rect) Handles Paint
g.DrawRectangle(0,0,me.Width,me.Height)
g.FontName = "Arial"
g.FontSize = 20
g.DrawingColor = Color.Blue
g.DrawText("Hello!", 40, 40)
End Sub
Move this code to a new method
Sub Draw(g as graphics)
g.DrawRectangle(0,0,me.Width,me.Height)
g.FontName = "Arial"
g.FontSize = 20
g.DrawingColor = Color.Blue
g.DrawText("Hello!", 40, 40)
End Sub
Change the paint event to
Sub Paint(g As Graphics, areas() As REALbasic.Rect) Handles Paint
Draw(g)
End Sub
Add a button for Save. In the Action event put
dim p as new Picture(canvas1.Width, Canvas1.Height)
Draw(p.Graphics)
// save p to disk
That will produce the exact same image you’re creating in Paint, but not incur the wrath of the OS. And you’re not really changing much code, just the location of that code. Does that make it any clearer?