BCB: как перебрать элементы управления на форме? - PullRequest
2 голосов
/ 06 марта 2010

Я ищу код BCB для перебора элементов управления в форме и получения некоторой информации о них.

Я пытался использовать myForm->ControlCount и typeid(myForm->Controls[i]), но это доставило мне несколько проблем.

1) typeid(myForm->Controls[i])->Name всегда дает "TControl *", и я надеялся на "TEdit *", "TMemo *" и т. Д.

Можно ли обойти это, используя

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

а затем кастинг? (если так, как лучше разыграть?)

2) как я могу (возможно, путем приведения) получить свойства элемента управления? например, имя, ширина, высота и т. д.

Я действительно ценю реальный код здесь (или URL некоторого фактического кода); Благодарю.


Обновление: поскольку мне нужно только протестировать 5 или 6 различных типов элементов управления для моего конкретного случая, я подумал, что, возможно, я мог бы попробовать dynamic_cast<> каждый для каждого из них по очереди, но я не могу этого получить на работу ...

Ответы [ 3 ]

8 голосов
/ 07 марта 2010

Вы несколько правы, полагая, что кастинг будет хорошей идеей и что использование dynamic_cast - лучший вариант здесь.

Если вы хотите перебрать элементы управления формы (или любого другого контейнера). К сожалению, у меня нет C ++ Builder на этом компьютере, поэтому я не могу протестировать код, который я вам даю, хотя это должно быть тривиальной задачей.

// 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...
}

Вам не нужно делать функцию рекурсивной для дочерних элементов управления дочерних элементов управления, они также включены в VCL. На мой взгляд, это самое простое решение для тестирования конкретных типов. Я также стараюсь максимально избегать функций RTTI, но это только я.

Как вы видите, мой пример также показывает, как вы можете получить доступ к свойствам и функциям элемента управления, даже тем, которые относятся к определенному типу. Однако те, о которых вы упомянули: Name, Width и Height, являются общими для TControl, и для получения доступа к ним не нужно использовать приведение.

Надеюсь, это помогло вам, из моего примера должно быть ясно, что переменная container может быть заменена на myForm, которую вы используете в своей.

1 голос
/ 10 октября 2018

Вот оно:

void EnumerateAll(TComponent *container)
{
   // Enumarate its children
   for (int i = 0; i < container->ComponentCount; i++)
      {
      // extract the control at index i
      TComponent *child = container->Components[i];

      if ( child->InheritsFrom (__classid(TComponent)) )    //this check is optional
         Form3->Memo->Lines->Add(child->Name);
      }
}

Использование:

EnumerateAll(MyForm);

Приведенная выше функция будет также перечислять пункты меню.
См. Также: C ++builder - перечисление компонентов в TPanel

Вот более подробная информация об иерархии VCL: http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Class_library

1 голос
/ 04 марта 2012

Это тоже может вам помочь:

for (int index = 0; index < ControlCount; index ++)
{
    if(Controls[index]->InheritsFrom(__classid(TCustomEdit)))
    {
        TCustomEdit *edit = (TEdit*) Controls[index];
        edit->Text = "Ok";
    }
}
...