Pregunta

Tengo un formulario con un montón de controles, y quería recorrer todos los controles de un panel determinado y habilitarlos / inhabilitarlos.

He intentado esto:

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

Pero eso no hizo nada. Resulta que todos los componentes están en la colección de componentes del formulario, no en su objeto principal. Entonces, ¿alguien sabe si hay alguna manera de obtener todos los controles dentro de un control? (Además de una solución fea como esta, que es lo que terminé por hacer):

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

Alguien, por favor, dime que hay una mejor manera ...

¿Fue útil?

Solución

Está buscando la matriz TWinControl.Controls y la propiedad ControlCount que la acompaña. Esos son para los hijos inmediatos de un control. Para obtener nietos, etc., utilice técnicas recursivas estándar.

Realmente no desea que la matriz Components (que es lo que itera el for - in ) ya que no tiene nada para Hacer, en general, con la relación padre-hijo. Los componentes pueden poseer cosas que no tienen relación con los hijos, y los controles pueden tener hijos que no tienen.

También tenga en cuenta que deshabilitar un control implícitamente deshabilita todos sus hijos, también. No puedes interactuar con los hijos de un control discapacitado; el sistema operativo no les envía mensajes de entrada. Sin embargo, para hacerlos parecer inhabilitados, deberá deshabilitarlos por separado. Es decir, para hacer que un botón tenga texto en gris, no es suficiente deshabilitar a su padre, aunque el botón no responda a los clics del mouse. Debe deshabilitar el botón para que se pinte " deshabilitado. & Quot;

Otros consejos

Si deshabilita un panel, todos los controles en él también están deshabilitados.

Solución recursiva con métodos anónimos:

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;

Esta es una forma de 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;

Simplemente

Panel.Enabled := Value;

Sé que esta publicación es un poco antigua, pero vine aquí en base a una búsqueda de la misma información. Aquí hay un código de C ++ que elaboré para cualquier persona interesada.

// 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);
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top