Canvas as a Page

Hi All,
Another prob for anyone interested.

This is all on Mac dekstop. I have “mastered” printing to my printer using the graphics object. To do this I first
“Var g As Graphics”
“Var settings As String
Var p As New PrinterSetup”
these are used to set various printer setting etc
and finally
g = OpenPrinterDialog
Now, the last one tells g that all the rest of the commands will go to the printer. I’m sure you all understand this. I don’t totally but, after a lot of experimenting I managed to get this to work and use it on several apps to print to my printer.

Now, the new problem is, I want to do the same but to a screen window and in a form that can scroll. I thought a canvas would be the way to do it - am I right?

If so, how do I tell the graphic object to “write” to that canvas?

I’ve looked through the docs and they mainly talk about placing a “picture” there and the example code put a copy of the button I press to intitiate the code into my canvas. I can place code into the “Paint” event of the Canvas and it works perfectly but that is static - ie it is the same every time. I thought this would be the way to go but if I try to access that event with Canvas.Paint I get the error that that event does not exist and, I’m not sure what I need to send there anyway.

Finally, and this is important, I looked at one of the example Apps and it gets VERY complicated with “extra” Objects where it appears the events and methods have been rewritten. That stuff is beyond my understanding as a hobbiest, so if that is the only way to go, please let me know up front and I’ll give up.

Anyway, sorry this is so long, is there a way to “print” to a canvas in the way you can print to a page in a printer?

As usual,
Thanks for any help.

There are 3 ways to “print” something.

  1. Get a graphics object from a printer. You have done this.
  2. Get a graphics object from a Picture.
  3. Use the graphics object in a canvas Paint event.

Once you have a graphics object, the drawing code is identical.

In order to cause a canvas Paint event to happen, you call Refresh on the canvas.

Thanks Tim.

So I whilst I understood “what” you said, I wasn’t sure I was gonna know how to do it. With a little playing on the docs I ended up with this:
var p As New Picture(340, 280, 32)
p.Graphics.DrawText(“Barry”, 10,10)
canvas1.Backdrop = p

Is that it, or are you thinking something different? I should say, it looks like it will work. Obviously many (many!!) more lines than just “Barry”, before I send it, but it works.

Also, the 3 numbers sent to “Picture”. I can’t find reference to them. I’m assuming the first 2 might be the H & W dimensions of the Picture, what’s the 32? Or are they something totally different?

Thanks again.

To clarify, you want to move your code into the Canvas.Paint event, and draw directly to the Graphics object it provides instead of a Graphics object you created.

 Event Paint(g As Graphics, areas() As Rect)
   'p.Graphics.DrawText("Barry", 10,10)
   g.DrawText("Barry", 10,10)
 End Event

You can then trigger the Paint event by calling Canvas.Refresh().

Hi Andrew,
Thanks. Problem as I see it with the Paint event, is that it is the same every time it is called, even as in your example. The bit of code I put in my reply to Tim appears to work. However that now leads to my next query/clarification with you guys. After I put the graphics onto the Canvas, I then thought I’d be able to scroll it, but it appears I can’t.

To clarify, the graphics I want to write will be a vertical timeline stretching over several weeks.

Anyway, I tried to scroll it and, Im thinking my problem is, I ca’t actually scroll a canvas, I can only scroll the “contents” of one, am I correct? In another part of the App, I have vertically placed some panels on another canvas (in an array) and I can scroll them. If I am correct, would it work to create a container that has a canvas on it, then embed that container into the “scrolling” canvas and write to that instead? I hope that all makes sense.
IE - Create Container with Canvas (called canvasContainer) - this is set to be longer than the screen height
CanvasContainer is then embeded into Canvas2
Scrolling Canvas2 then makes the canvasContainer scroll.


Make p a property of the window, not a local variable. Don’t set it to the canvas backdrop, draw it in the paint event. Now it is content of the canvas and can be scrolled.

p = New Picture(340, 280, 32)
p.Graphics.DrawText(“Barry”, 10,10)

AT the risk of restating what someone else has said, there are a couple of ways you can do this scrolling in your canvas.

The first is not to change your drawing code at all.
Your drawing code goes in a method called something like

sub DrawEverythingOnaGraphic(g as graphics)

To print, you call that and pass the g you get from the printerdialog

To create a picture, you make a big enough picture, and you call the routine with the picture’s graphic property

To display in a canvas, you use the picture in the canvas’ Paint event, but when you draw the picture, you offset the Y position: eg if you want to scroll the image UP by 100 pixels…

sub Paint(g as graphics)
g.drawpicture  theReadyDrawnPicture, 0, -100,theReadyDrawnPicture.width, theReadyDrawnPicture.height
end sub


The other way is to modify the drawing code so that it draws everything with an x/y offset

sub DrawEverythingOnaGraphic(g as graphics, xoffset as integer, yoffset as integer)
g.DrawText(“Barry”, 10 + xoffset,10 + yoffset)
end sub

And if you do that, then your Canvas Paint event to scroll up by 100 would look like this:

sub Paint(g as graphics)
    DrawEverythingOnaGraphic g,0, -100
end sub

or to actively scroll it, maybe tie it to a scrollbar valuechanged event:

sub Paint(g as graphics)
    DrawEverythingOnaGraphic g,0, theScrollbar.value * -1
end sub

sub ValueChanged()
end sub
1 Like

Thanks everyone,
As usual, I love the replies as it always gives me something to play with and learn new stuff.

I’ll definitely have a look at everything you’ve all given me. In the meantime, FWIW, I had a go at what I talked about earlier. I created a container object that had a canvas on it. I then embedded that onto the background canvas and wrote to it. I can then scroll that container and it works ok.

Anyway, I will investigate and play with all your suggestions. As you prob know, 1 little thing you learn can lead onto a dozen other things that come in useful elsewhere :slight_smile:

Thanks guys,

In 2005, we decided to rewrite all of our software in Xojo (RB at the time). I can’t tell you how many times a staff meeting went, “We need to implement XYZ”, and I would think, “I just read about that on the forum!”

I wish one of those implementations was “we should return easy borders to list cells” :kissing_smiling_eyes:. But that’s for another thread :slight_smile:

Thanks for your help - as always.

If you encapsulate your drawing with a class and plan your drawing carefully, you can use the same class to draw to Canvas, PDF, and Printers. Write once, use many is one of the great powers of object oriented design.

I am not sure if there are tutorials or examples on how to do this, it’s something I learned from Bob and Shorts Reports.

Hi Tim,
Thanks. Yeah, as I’ve often said here I’m not a pro and I have been “playing” with programming since the days of MSDOS, going through Visual Basic, Pascal and Turbo Pascal before I moved to Macs in (I think) around 2006. I was delighted when I came across Real Basic (which of course become XOJO) as I was able to continue my hobby.

Anyway, the one thing I have sadly never been able to come to grips with is Object Oriented programming under either system. For some reason it just escapes me. Possibly comes under the old “can’t teach a new dog…” category.

Barry :slight_smile: