Question

I want to create a rectangle button field (using list). The "cells" in this field are basically buttons, the only thing I need to change is the OnClick event handler (I want it to check some button properties and take some action according to them). I did something like this before in MSVS 2013, using C++/CLR, I just wrote the method I wanted to work as an event handler, added event handler variable to the "cell" constructor, and assigned it as a new event handler while "filling" the list. It looked something like this:

.h

cell(<...>, System::EventHandler^ eh) : {
        <...>;
        Click += eh;
    }

.cpp

List^ list = gcnew List(<...>, gcnew System::EventHandler(^Form1, &Form1::cell_Click));

Mr. Google told me that in C++ Builder inheritance of managed objects is not just writing a colon after the class declaration, it's a process called "Creating component".

Since I don't need to re-use this little piece of code, I don't want to create any packages or use existing. So I create a unit.

The questions are:

  1. Where to write event handler declaration in header?
  2. Where to write event handler implementation in .cpp file?
  3. How do I actually use the written unit in the project I added it to? I mean, can I just declare a variable of the custom inherited type in the project files?
Was it helpful?

Solution

C++Builder uses C++ as its language, not "Managed C++". there is no ^ pointer types and no gcnew, or "managed objects".

To make an event handler easily, select the control in the form editor and press F11. That will bring up the Object Inspector. Select the "Events" tab and then double-click the handler you want to create. This will create the code you need, you just have to fill in the function body.

If you double-click on the control, it's a shortcut to create the most common event handler for that object (which is actually OnClick for a button, so you could just double-click your button).

(In older versions of C++Builder, if you saved your project before typing anything in the function body, it would very kindly delete the handler, which was pretty annoying -- XE5 no longer does that).

I don't quite understand what you are talking about in some of your post - why do you want to inherit from the button? I figured from your opening paragraph that you just want to create a bunch of buttons at runtime, and implement the OnClick handler.

If you mean that you just want to create a lot of buttons at runtime, then you can do it like this:

TButton *b = new TButton(this);   // 'this' will be responsible for deleting the button
b->Parent = this;    // `this` will be responsible for displaying the button
b->Caption = "hello";
b->OnClick = Button1->OnClick;
// set other properties

AFAIK there is no easy way to clone a button. You have to make a new button like this, and then copy the values you want from another button. Properties you don't set will have their default values.

If you use this method (i.e. make Button1 in the form editor and then copy its OnClick to your other buttons) it is nice and easy. You could actually delete your Button1 after you have used it to auto-generate the OnClick handler and give you the right function signature.

You could also store the pointers to each button in a list , e.g. std::list<TButton *>. Be mindful of button lifetimes when doing this: the fact that the button's Owner is the form means that the form will delete them during the form destruction. You should not try to delete these pointers yourself, and you should not use them during or after the form destruction.

Inside the OnClick handler, you can get a pointer to its Button by doing:

TButton *b = dynamic_cast<TButton *>(Sender);

Then you can use b->Tag or some other property of the button to identify which button was clicked.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top