tags:

views:

149

answers:

1

I am looking for some BCB code to iterate over the controls on a form and get some information about them.

I tried using myForm->ControlCount and typeid(myForm->Controls[i]) but this gave me a few problems.

1) typeid(myForm->Controls[i])->Name always gives "TControl *" and I was hoping for "TEdit *", "TMemo *", etc

Can I get round that by using

if (typeid(myForm->Controls[i]) == typeid(TEdit))

and then casting? (if so, how best to cast?)

2) how can I (probably by casting) get the properties of the control? e.g, Name, Width, Height, etc?

I woudl really appreciate actual code here (or a URL of some actual code); thanks.


Update: Since I only need to test 5 ot 6 different types of controls for my specific case, I thought I could maybe try to dynamic_cast<> each to each of them in turn, but I can't seem to get that to work ...

+2  A: 

You are somewhat correct in your assumption that casting would be a good idea and that using dynamic_cast is the best option here.

If you want to iterate over the controls of a form (or any other container). Unfortunately I don't have my C++ Builder on this computer so I am unable to test the code I give you, should be a trivial task to create though.

// You wanna start my iterating through the controls of the container
for (int i = 0; i < container->ControlCount; i++)
{
    // Let us extract the control at index i
    TControl *control = container->Controls[i];

    // Now we want to test whether this is any specific type, for instance a
    // TEdit or any TEdit descendant.
    TEdit *edit = dynamic_cast<TEdit *>(control);

    // If this control is a TEdit or any control deriving from it, we will have 
    // a pointer to it, if this is any other type, we will be left with a zero
    // pointer.
    if (edit)
    {
        // This is a TEdit control... we can now access TEdit only properties.
        edit->Text = "This is an edit control.";
    }

    // We do the same if we want to test for a TButton...
    TButton *button = dynamic_cast<TButton *>(control);

    // Again we test whether this was actually a button
    if (button)
    {
        // It is a button, again we can access TButton only properties...
        button->Caption = "This is a button"; 
        // Yeah ok not a TButton only one, but couldn't think of any.
    }

    // And so on...
}

You do not need to make the function recursive for child controls of child controls, these are included here as well by the VCL. This is in my opinion by far the simplest solution for testing for specific types. I also try to avoid the RTTI features as much as possible, but that is just me.

As you can see my example also shows how you can access properties and functions of the control, even those specific to a certain type. However the ones you mention: Name, Width and Height are all common to TControl and it should not be necessary to cast to access these.

Hope this has helped you out, it should be clear from my example that the variable container can be replaced by myForm which you use in yours.

TommyA
Thanks, Tommy. I had given up and coded it is Pascal using the `is` operator. It's great to be able to do it in c++.YOu say '"You do not need to make the function recursive for child controls of child controls, these are included here as well by the VCL"` - but what would happen if I had, say a TRadioGroup, or some controls on a TPanel? Are they picked up by your code?
Mawg
btw, I did have to recurse for TPanel and TGroupBox
Mawg
The Controls[] list is specific to the Parent that you are accessing. Nested child controls must be handled with recursion.
Remy Lebeau - TeamB
Depending on whether third-party controls need to be handled, it ay be more beneficial to cast to TCustom... classes instead, such as TCustomEdit, TCustomButton, etc.
Remy Lebeau - TeamB
Also, using C++'s typid() on VCL classes does not usually work. If you want to get the string representation of a class's name, use the TObject::ClassName() method, which will return the derived class name as expected, ie: Control->ClassName()
Remy Lebeau - TeamB
Although I agree that recursion is needed, the lack of it in my example is from the situation of not having a C++Builder on the machine I wrote the post from, so had to base my answer purely on what I could remember (or not remember). However I fail to see why `typeid` comment is made to my post and not the authors. Since I am deliberately avoiding the `typeid` and stick to the `dynamic_cast` to identify the class.
TommyA

related questions