Есть ли способ получить все элементы управления на контейнере? - PullRequest
13 голосов
/ 06 января 2009

У меня есть форма с кучей элементов управления, и я хотел перебрать все элементы управления на определенной панели и включить / отключить их.

Я пробовал это:

var component: TComponent;
begin
  for component in myPanel do
    (component as TControl).Enabled := Value;
end;

Но это ничего не сделало. Оказывается, все компоненты находятся в коллекции компонентов формы, а не их родительских объектов. Так кто-нибудь знает, есть ли способ получить все элементы управления внутри элемента управления? (Помимо уродливого обходного пути, подобного этому, что я и сделал в итоге):

var component: TComponent;
begin
  for component in myPanel do
    if (component is TControl) and (TControl(component).parent = myPanel) then
      TControl(component).Enabled := Value;
end;

Кто-то, пожалуйста, скажите мне, что есть лучший способ ...

Ответы [ 5 ]

25 голосов
/ 06 января 2009

Вы ищете массив TWinControl.Controls и сопровождающее свойство ControlCount. Те для непосредственных детей контроля. Чтобы получить внуков и т. Д., Используйте стандартные рекурсивные приемы.

Вы на самом деле не хотите, чтобы массив Components (что итерирует цикл for - in), так как он вообще не имеет ничего общего с отношениями родитель-потомок. Компоненты могут владеть вещами, которые не имеют дочерних отношений, а элементы управления могут иметь дочерние элементы, которых они не имеют.

Также обратите внимание, что отключение элемента управления неявным образом отключает также все его дочерние элементы. Вы не можете взаимодействовать с детьми отключенного элемента управления; ОС не отправляет входные сообщения им. Чтобы сделать их выглядящими отключенными, вам нужно отключить их отдельно. То есть, чтобы сделать текст кнопки серым, недостаточно отключить родительский элемент, даже если кнопка не будет реагировать на щелчки мышью. Вам нужно отключить саму кнопку, чтобы она нарисовала себя «отключено».

13 голосов
/ 06 января 2009

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

Рекурсивное решение с анонимными методами:

type
  TControlProc = reference to procedure (const AControl: TControl);

procedure TForm6.ModifyControl(const AControl: TControl; 
  const ARef: TControlProc);
var
  i : Integer;
begin
  if AControl=nil then
    Exit;
  if AControl is TWinControl then begin
    for i := 0 to TWinControl(AControl).ControlCount-1 do
      ModifyControl(TWinControl(AControl).Controls[i], ARef);
  end;
   ARef(AControl);
end;

procedure TForm6.Button1Click(Sender: TObject);
begin
  ModifyControl(Panel1,
    procedure (const AControl: TControl)
    begin
      AControl.Enabled := not Panel1.Enabled;
    end
  );
end;
2 голосов
/ 24 марта 2012

Вот путь Delphi 2007:

procedure TForm6.ModifyControl(const AControl: TControl; const value: Boolean);
var
  i: Integer;
begin
  if AControl=nil then Exit;
  if AControl is TWinControl then begin
    for i := 0 to TWinControl(AControl).ControlCount-1 do
      ModifyControl(TWinControl(AControl).Controls[i], value);
  end;
  Acontrol.Enabled := value;
end;

procedure TForm6.Button1Click(Sender: TObject); 
begin 
  ModifyControl(Panel1, true);  // true or false
end;
1 голос
/ 06 января 2009

Просто

Panel.Enabled := Value;
0 голосов
/ 04 декабря 2013

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

// DEV-NOTE:  GUIForm flattens the VCL controls
// VCL controls are nested.  I.E. Controls on a
// Panel would have the Panel as a parent and if
// that Panel is on a TForm, TForm's control count
// does not account for the nested controls on the
// Panel.
//
// GUIControl is passed a Form pointer and an index
// value, the index value will walk the controls on the
// form and any child controls counting up to the idx
// value passed in.  In this way, every control has a
// unique index value
//
// You can use this to iterate over every single control
// on a form.  Here is example code:
//
// int count = 0;
// TForm *pTForm = some_form
// TControl *pCtrl = 0;
// do
// {
//      pCtrl = GUIControl(pTForm, count++);
//
// }while(pCtrl);

TControl *GUIControl(TForm *F, int idx)
{
    TControl *rval = 0;
    int RunCount = 0;

    for(int i=0; i<F->ControlCount && !rval; i++)
    {
        TControl *pCtl = F->Controls[i];

        if(RunCount == idx )
            rval = pCtl;
        else
            rval = GUIChildControl( pCtl, RunCount, idx);

        RunCount++;
    }

    return(rval);
}

TControl *GUIChildControl(TControl *C, int &runcount, int idx)
{
    TControl *rval = 0;
    TWinControl *pC = dynamic_cast<TWinControl *>(C);
    if(pC)
    {
        for(int i=0; i<pC->ControlCount && !rval; i++)
        {
            TControl *pCtrl = pC->Controls[i];
            runcount++;

            if( runcount == idx)
                rval = pCtrl;
            else
            {
                TWinControl *pCC = dynamic_cast<TWinControl *>(pCtrl);

                if(pCC)
                {
                    if( pCC->ControlCount )
                        rval = GUIChildControl(pCtrl, runcount, idx);
                }
            }
        }
    }

    return(rval);
}
...