Hi, I am trying to make small game , but I am confronting with a problem. I have a function that should add a new button to my form when it's called. The problem is that I don't know how to create a new object (a button, a shape or whatever...) and adding it to my form. In Java, this would be fairly simple, but how do I it here ? my header file contains the form class:

class TForm1 : public TForm
{
__published:	// IDE-managed Components
        TShape *Shape1;
        TButton *Button1;
        void __fastcall Button1Click(TObject *Sender);
private:	// User declarations
public:		// User declarations
             TButton *TestBtn ;
        __fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;

At public I've added a test button (TestBtn). The same problem: how can use it ? It must be first allocated (and how)?

Thanx !

//...
void __fastcall TForm1::example(void)
{
     TestBtn = new TButton();
     TestBtn->Visible = false;
}

Still doesn't work !It gives me this error :
" E2285 Could not find a match for 'TButton::TButton()' "

Header required for 'TButton' is missing i think.

TButton's constructor needs to be passed a pointer to a TComponent (eg a parent form) that is responsible for managing the button.

It is also necessary to set various attributes: position, caption, visibility, the function to be called when the newly created button is created, etc etc. TButton is derived from TWinControl, so some inherited attributes probably also need to be set.

It would probably be easier to create a button on your form at design time, and have your function make that button visible as needed.

TestBtn = new TButton(this);
TestBtn->Parent = this;
TestBtn->Caption = "Check";

Ok , this sorted things out a little bit. My next problem is, how to assign each button a different function when it's pressed.For example I do something like this:

for (x = 0; x < 10; x++)
{
TButton *TestBtn = new TButton(this);
TestBtn->Caption = "My button " + IntToStr(x);
TestBtn->Top = 100;
TestBtn->Left = 100 + 10 * x;
TestBtn->OnClick = myfunction(x);
TestBtn->Parent = this;
}

where myfunction is defined like this in the header file:

void __fastcall TForm1::myfunction(int x)
{
ShowMessage("Button " + IntToStr(x) + " clicked");
}

I get an "Not an allowed type" error when compiling. It seems that I can't pass a variable like this to myfunction. But, if I do like this: TestBtn->OnClick = myfunction; with myfunction looking now :

void __fastcall TForm1::myfunction(TObject *Sender)
{
ShowMessage("Button ? clicked");
}

it works, but it doesn't do what I wanted it to do.But how do I know which of the ten buttons is clicked now? How can I pass this information to the function?

Thanx,
Adrian

class TForm1:public TForm
{
      private:
           // create temp var..
           int m_x;
      //...
};

void __fastcall TForm1::myfunction1(int x)
{
     ShowMessage("Button " + IntToStr(x) + " clicked");
}

void __fastcall TForm1::myfunction(TObject *Sender)
{
     myfunction1(m_x);
}

//######################################

TButton *TestBtn = new TButton(this);
TestBtn->OnClick = myfunction;
TestBtn->Parent = this;

for (x = 0; x < 10; x++)
{
    TestBtn->Caption = "My button " + IntToStr(x);
    TestBtn->Top = 100;
    TestBtn->Left = 100 + 10 * x;
    m_x = x;
    TestBtn->OnClick(this/*sender*/);
}
//######################################

This works only if the buttons are clicked immediately after they're created.After that that , any button I click , it shows the same : "Button 9 clicked" (and that's logic, m_x has the latest value, and that's 9). How to do , to stick to each button it's attributes(here, it's id) ?

try yhis...

//######################################

class TForm1:public TForm
{
    //...
    public:
        TButton *TestBtn[10]
    //...
};

//######################################

for (x = 0; x < 10; x++)
{
     TestBtn[i] = new TButton(this);
     TestBtn[i]->Parent = this;
     TestBtn[i]->OnClick = myfunction;
     TestBtn[i]->Caption = "My button " + IntToStr(x);
     TestBtn[i]->Top = 100;
     TestBtn[i]->Left = 100 + 10 * x;
     m_x = x;
}

//######################################

Still, I didn't managed to solve it :( . My question remains: how can I pass a variable to the function that it's executed when my button is pressed. I want (if it's possible) to do

TestBtn->OnClick = myfunction(parameter);

???

Still, I didn't managed to solve it :( . My question remains: how can I pass a variable to the function that it's executed when my button is pressed. I want (if it's possible) to do

TestBtn->OnClick = myfunction(parameter);

???

...?...
it's "Not an allowed type", :( ...Sorry...:)
...!...

void __fastcall TForm1::OnClick1(TObject *Sender)
{
         ShowMessage("Button1 clicked");
}

void __fastcall TForm1::OnClick2(TObject *Sender)
{
         ShowMessage("Button2 clicked");
}

void __fastcall TForm1::OnClick3(TObject *Sender)
{
         ShowMessage("Button3 clicked");
}

//... repeat until "void __fastcall TForm1::OnClick10(TObject *Sender)"...

//######################################
for (x = 0; x < 10; x++)
{
    TestBtn[i] = new TButton(this);
    TestBtn[i]->Parent = this;
    switch(i)
    {
        case 0:
            TestBtn[i]->OnClick = OnClick1;
        break;
        case 1:
            TestBtn[i]->OnClick = OnClick2;
        break;
        case 2:
            TestBtn[i]->OnClick = OnClick3;
        break;

        //... repeat until case 9..
   
    }
    TestBtn[i]->Caption = "My button " + IntToStr(x);
    TestBtn[i]->Top = 100;
    TestBtn[i]->Left = 100 + 10 * x;
}

try it...

You need to understand the difference between registering a callback function and actually calling it.

Setting TButton's OnClick event egisters a function that will be called when the user - eventually - presses the button. It does not call the function directly.

If, when the user presses the button, you want a particular function called, then call your function within the callback function (eg in the body of OnClick1). If you register the callback (eg TestBtn->OnClick = OnClick1;), then OnClick1 callback will be called whenever a user presses TestBtn. If OnClick1 calls myfunction(parameter) ......

Ok, so it seems that the only way is to make an array of functions( OnClick1, OnClick2,...and so on), and associate each function to a button. (like cikara21 said). I'll come back with the result......

Now here's how I've figured out to do it : in the header file I have a class

class C
{
public:
int val;
TButton *btn;

void __fastcall show(TObject *Sender)
{
ShowMessage("Button"+val);
}

};

Now, in the main I have:

C *test[10];
int i;

  for(i=0;i<10;i++)
  {
  test[i] = new C;
   
     test[i]->val=i;

    test[i]->btn = new TButton(this);
    test[i]->btn->Caption = "Buton " + IntToStr(i);
    test[i]->btn->Top = 100;
    test[i]->btn->Left = 100 + 100 * i;
    test[i]->btn->Parent = this;
    test[i]->btn->OnClick=test[i]->show;
   }

And THAT'S IT !!!!!!!!! I hope this thing will help anybody who has confronted with this problem. I would like to thank all of you who helped me , especially cikara21, who was a real helper ! Cheers mate !

congratulations...:)

You don't know how mutch you helped me!
Thank you very much!
Itamir Sartori - itamirsartory@yahoo.com.br

commented: Leave old posts as is. -2

Do this:

    Botton[x]->Tag = x;

    //################################

void __fastcall TForm1::myfunction(TObject *Sender)
{
        AnsiString Test;
        Test = (AnsiString)((TPanel*)Sender)->Tag;
        Memo1->Lines->Add(Test);
}

It worked wonderful to me!
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.