Add Canvas Control at Runtime

I am making a TCG type Card game and I am using a Canvas Array for each player’s hand. Since there is no way to know how many cards a player will be holding at a given time how do I add/remove, at runtime, a particular item in the Canvas array?

Don’t make a canvas array. Use ONE canvas. Read the SuperDraw article in xDev 12.5 about how to do drawing in an object oriented way.

Don’t have money to buy it. Plus there is no guarantee I’ll understand it.

Why not use one giant canvas and draw in the appropriate cards for each hand? That will let you do animations more easily as well since you don’t have to worry about the borders of controls.

Superdraw

Superdraw is on the web, couldn’t find the original download link. Xojo actually has an example like this I believe.

I’m doing it this way I as HAVE ZERO knowledge about doing it that way. I was using the ABCanvas from www.alwaysbusycorner.com but he has abandoned it and I have know idea what to do without his help.

Richard:

using an ending 1 (instead of 0) will make the download starting right now (instead of opening a tab, etc.)

Example with an ending 0: https://www.dropbox.com/s/fgd88uyribqccp6/SuperDraw4.rbp?dl=1

[quote=285547:@Emile Schwarz]Richard:

using an ending 1 (instead of 0) will make the download starting right now (instead of opening a tab, etc.)

Example with an ending 0: https://www.dropbox.com/s/fgd88uyribqccp6/SuperDraw4.rbp?dl=1[/quote]

Done. Thanks.

One major drawback to using an array of canvases is that you can’t control z-order. The last one added is always on top of all the others. Take a moment to examine the SuperDraw example and ask questions. It isn’t really that hard.

The SuperDraw example is all Japanese to me. I could barely even understand the ABCanvas examples and the creator helped me with what I have done so far but he has completely abandoned the project so I’m at a loss. This drawing to canvas using the Paint Event is all new to me and I’m just not understanding it.

I’m the kind of person who needs everything spelled out to me. You just can’t give me code and expect me to understand it. I even have issues with code I write myself. I’ll completely forgot what a block of code I wrote is supposed to do and why I wrote it.

Everyone here just tells me oh use this or check this example or use the Language Reference. None of that helps me as I need explicit details on what everything is, otherwise I can’t understand it.

To answer your original question, there are 2 ways to add a new canvas control to a window:

  1. Control Set. Add a canvas to the window and make it a control set (use the gear icon in the inspector, and fill in the Member Of field. Then in code you write
dim c as canvas
c = New ControlSetName

where ControlSetName is the name from the Member Of field.

  1. Container Control. Put the canvas in a container control that is the same size as the canvas. To create a new one and put it on the window, use
dim cc as ContainerControlName
cc = New ContainerControlName
cc.EmbedWithin(Window1, X, Y)

You would need to change the array of canvas into an array of containercontrol.

Hope that helps some.

This happens to all developers all the time. Learn a new programming language from time to time – you will be amazed how much this helps for programming languages you think you know and master well. Learn some thoroughly and some not so thoroughly (as the first needs a lot of time).

I’m the same. I even failed at the university because of that. And this also happens to all developers at some time (not the failing at the university though). If you know the code to be properly written code, re-type the whole code line by line (that’s the way I usually use to learn code I do not understand). Or follow the code in the debugger line by line and look a the values of each variable changing. Or instead of staring at the code, draw the parts you understand on paper and try to fill the parts you don’t understand in there. Some people like me must built a visual of an algorithm to understand it. And don’t give up early. I sometimes need several attempts. And several can easily be a two-digit number (I ain’t joking on that).

This happens to all developers. Alert, alert: This happens to all developers. Stating it twice is not enough: This happens to all developers. Comment your code in a way it states non-obvious stuff like the intention of the method or variable, possible side-effects, pre-conditions required to run the method, etc. And have a strict naming convention (for example long, self-explanatory instance, variable and method names – an example from Objective-C/Cocoa: automaticallyEnablesStillImageStabilizationWhenAvailable).

This happens to all developers. Learn to live with it. This is not meant offensive in any way, but example are there for that and the LR too. You can get better at understanding them over time by trying and re-trying.

This happens to all developers (well, depending on the complexity of the code). But you have already mastered some parts of programming with and in Xojo. How did this happen? By coincidence? No. And not everything was explained to you. Learn to watch yourself while you learn and grasp something. Then apply this strategy (as explained above for me this is usually copying code by stupidly re-typing it – somehow my brain reacts to typing code better than to copying and pasting code).

As for your question: if you don’t want to go with one canvas for all drawing – which I would do – I would recommend Tim’s example with the embedded ContainerControls. Note that with his example you don’t need to put a Canvas on the ContainerControl, you can paint the stuff directly in the ContainerControl’s paint event.

Good point.

I started with BASIC over 15 years ago. Then moved to Visual Basic 6. Then when Microsoft completely changed everything in Visual Basic .NET I discovered RealBasic. A lot of what I know came from explicit tutorials where everything was explained really well.

I tried to learn C many times over the years and can’t even understand the simple “Hello World” code.

Is anyone familiar with the ABCanvas project from Always Busy Corner? Or can help me understand the code so I can do what I’m trying to do?

Charles, the best way is indeed to do everything in a single canvas Paint.

BUT, and I am sorry if that spawns controversy, I think you should go for what you know how to do today and get the game going. When you complete this first project, or at least a working prototype, that will encourage you to explore more sophisticated possibilities, but at least, you will already have something.

You can create new canvases very easily.

  • Put a first canvas on the window
  • Click the gear icon on top of the Inspector
  • Make the canvas member of a new control set. Let us say your control set is called Canvas1.
  • Add to the window a property
myCanvases() as Canvas1
  • Add your first canvas to the array
    myCanvases.append Canvas1(0)
  • To create a new canvas, do :

myCanvases.append new Canvas1 myCanvases(myCanvases.ubound).Left = 0 myCanvases(myCanvases.ubound).Top= 0

Note that I create a new canvas with the method New, and immediately affect it to a new element in myCanvases. Then I use this element of myCanvases() as a regular canvas.

By keeping a reference in the array myCanvases, you will then be able to refer to any one of the created canvases. You will be able to change their left and top to move them, and make them disappear like so :

myCanvases(0).close

Above, I have added the first canvas to the array. That is so the index in the control set and in the array be the same. In the example above, the canvas dragged over the window can be access as myCanvases(0), and the first created canvas will be myCanvases(1), and so on.

Control Sets work a bit differently than regular controls. Instead of having events for each control, each event fires for all controls (not at the same time, though, just at the same place). To differenciate between elements of the control set, you use their index. For instance, to know which canvas was clicked, you can do :

Function MouseDown(index as Integer, X As Integer, Y As Integer) Handles MouseDown as Boolean Msgbox str(index) End Function

By testing the index, you know which element has had an event.

Good luck.