array of TRectangles in FMX

  

I am trying to extend the code from this from using one TRectangle to using multiple rectangles that can be added at runtime. In that example the code to click on and drag applies only to that one TRectangle Rectangle1. I need to make it more general so it works on any recangle I add to the form (the rectangles won’t be there at design time). I found this code to create a custom class and it works fine to create new rectangles. I can assign methods that run when they are clicked on but i think it is the wrong path to go down due to being a separate class from TForm1…and many of the data points i need to make my code work are from TForm1 (positions etc.).

In short, i want to be able to add TRectangles at runtime and run code on normal events (when rectangle is clicked on, mouseup etc.) for that specific rectangle.

Not sure where to start…but first I think i need to know how to make an array of controls that can be accessed something like this:

rectangles[i]->Position->X = …

And then have events that fire when the rectangles are clicked on that can act on that i’th rectangle:

void __fastcall TForm1::rectsMouseDown(TObject *Sender, TMouseButton Button,
TShiftState Shift, float X, float Y){
rectangles[i]->Position->X = ….
rectangles[i]->Position->Y = …..
}

UPDATE 1: I am able to create a vector of TRectangles and manipulate them through the vector. Now, how can i access their events to run code (e.g. OnClick)? Here is what i have so far:

#include <vector> // in my cpp file

std::vector<TRectangle*> myRects; // in my cpp file outside of any function so it is global

void __fastcall TForm1::Button3Click(TObject *Sender)
{
TRectangle *R = new TRectangle(this);
R->Parent = this;
R->Position->X = 20 + 5*myRects.size(); // slightly offset them in space
R->Position->Y = 20;
R->Tag = myRects.size()+1; // i think this is how i will tell them apart
myRects.push_back(R);
}

I can move a rectangle like this:

void __fastcall TForm1::Button4Click(TObject *Sender)
{
myRects[1]->Position->X = 50; // this moves rectangle number 2.
myRects[1]->Position->Y = 50;
}

UPDATE 2: With Remy’s direction i have it working now! I added R->OnClick = &myRectOnClick; to my Button3Click method right above the push_back. Then i added the following method to my TForm1.

void __fastcall TForm1::myRectOnClick(TObject *Sender)
{
if (TRectangle *Re = dynamic_cast<TRectangle *>(Sender)) { // make sure result of cast is not null
ShowMessage(“Rectangle ” + IntToStr(Re->Tag)); // Tag is how i know which rectangle i’m dealing with
}
}

UPDATE 3: Not sure if this should be a new question…but I added a PopupMenu1 that i want to invoke with right-click on the rectangles. I incorporated it with R->PopupMenu = PopupMenu1 in theButton3Click code. The MenueItem1Click event just does a ShowMessage displaying the rectangles number (currentR). Well, the global int currentR for the rectangle doesn’t get set when i just right-click on a rectangle. I have to left-click first, and then right-click for currentR to get set to this rectangles tag. Below is my code for the mouse down event on a rectangle – seems like it should always set currentR to the present rectangle regardless of left or right click.

void __fastcall TForm1::myRectOnMouseDown(TObject *Sender, TMouseButton Button,
TShiftState Shift, float X, float Y)
{
if (TRectangle *Re = dynamic_cast<TRectangle *>(Sender)) { // make sure result of cast is not null
currentR = Re->Tag; // which rectangle
if (Button == 0) { // left mb
fMouseIsDown = true;
fMouseInRectAtClick.X = X;
fMouseInRectAtClick.Y = Y;
}
}
}

For clarity here is my latest version of the Button3Click code that places a new rectangle on the form:

void __fastcall TForm1::Button3Click(TObject *Sender)
{
TRectangle *R = new TRectangle(this);
R->Parent = this;
R->Position->X = 20 + 5*myRects.size();
R->Position->Y = 20;
R->Tag = myRects.size()+1;
R->OnMouseDown = &myRectOnMouseDown;
R->OnMouseUp = &myRectOnMouseUp;
R->OnMouseMove = &myRectOnMouseMove;
R->PopupMenu = PopupMenu1; // to get a popup menu
myRects.push_back(R);
}

Comments are closed.