Есть ли какой-нибудь способ получить все элементы управления в контейнерном элементе управления?

StackOverflow https://stackoverflow.com/questions/414928

Вопрос

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

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

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;

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

Это было полезно?

Решение

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

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

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

Другие советы

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

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

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;

Вот способ 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;

Просто

Panel.Enabled := Value;

Я знаю, что это сообщение немного старое, но я пришел сюда на основе поиска той же информации. Вот код 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);
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top