Inicio > Delphi, Trucos > Modificar propiedades de controles en ejecución utilizando RTTI

Modificar propiedades de controles en ejecución utilizando RTTI

miércoles, 5 de diciembre de 2007 Dejar un comentario Ir a comentarios
Share Button

A veces durante la ejecución de código necesitamos modificar una determinada propiedad de diferentes tipos de controles. Para la explicación podemos pensar por ejemplo en como desactivar (Enabled=False) todos los controles de un formulario; Una primera opción podría ser un código como éste:

// recorrer los controles
for i := 0 to (Self.ComponentCount - 1) do begin
 
   // Es un Edit
   if (Components[i] is TEdit) then
   TEdit(Components[i]).Enabled := False;
   // Es un LAbel
   if (Components[i] is TLabel) then
   TLabel(Components[i]).Enabled := False;
   // Es un ListBox
   if (Components[i] is TListBox) then
   TListBox(Components[i]).Enabled := False;
   ...
end;

Una implementación como ésta tiene muchos problemas e inconvenientes; Los más claros podrían ser:* Es poco «ortodoxa», por decirlo así;

  • Es un código repetitivo y nada eficiente.
  • Es por definición incompleta, ya que el número de componentes que podemos tener en un form es inmenso y de muchas clases (yo sólo las básicas que trae Delphi).
  • Es poco flexible.

Utilizando RTTI podemos de forma relativamente sencilla modificar todos los componentes utilizando una única instrucción.
Podemos utilizar un procedimiento como éste:

{:Asigna valor a una propiedad a través del Nombre (RTTI). }
function SetPropAsString(AObj: TObject; const PropName, Value: String):Boolean;
var
   PInfo: PPropInfo;
begin
   // Intentamos acceder (con un puntero) a la info. de la propiedad
   PInfo := GetPropInfo(AObj.ClassInfo, PropName);
   Result := PInfo <> nil;
   // Se ha obtenido la información...
   if (Result) then begin
      // Se ha encontrado la propiedad con éste nombre; Chequear el tipo...
      if (PInfo^.Proptype^.Kind = tkString) or
          (PInfo^.Proptype^.Kind = tkLString) then begin
        // Asignar el valor de tipo String
        SetStrProp(AObj, PInfo, Value);
      end
      else if (PInfo^.Proptype^.Kind = tkInteger) then begin
        // Asignar el valor...
        if (PInfo^.PropType^.Name = 'TColor') then begin
          SetOrdProp(AObj, PInfo, StringToColor(Value));
        end
      else if (PInfo^.PropType^.Name = 'TCursor') then begin
        SetOrdProp(AObj, PInfo, StringToCursor(Value));
      end
      else begin
        SetOrdProp(AObj, PInfo, StrToInt(Value));
      end;
   end
   else if (PInfo^.Proptype^.Kind = tkEnumeration) then begin
    // Bloque de proteccion
    try
      if (PInfo^.PropType^ = TypeInfo(System.Boolean)) then begin
        SetOrdProp(AObj, PInfo, StrToInt(Value));
      end
      else begin
        SetOrdProp(AObj, PInfo, StrToInt(Value));
      end;
    except
      raise;
    end;
   end
   else begin
    Result := False;
   end;
  end
  else begin
    // No se ha encontrado la propiedad con ese nombre
    Result := False;
  end;
end;

Su utilización es muy sencilla, y en el ejemplo anterior el código utilizado pasaría a ser similar a éste:

NOTA: Añadir la unit TypInfo al USES.

NOTA2: (Gracias Arsenio por comentarmelo) Se deben añadir al uses también las units Graphics y Controls ya que son usados por StringToColor y StringToCursor respectivamente.

// recorrer los controles
for i := 0 to (Self.ComponentCount - 1) do begin
   SetPropAsString(Components[i], 'Enabled', '0'{FALSE});
end;
// Otros ejemplos
SetPropAsString(Components[i], 'Left', '10');
SetPropAsString(Components[i], 'Color', 'clRed');
...
Vota este post
Categories: Delphi, Trucos Tags: , , ,
Subscribe
Notify of
guest

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

2 Comments
Inline Feedbacks
Ver todos los comentarios
Arsenio
9 years ago

Yo se que este post tiene años… pero hoy lo usé… y te agradezco… por este post y por todo el blog que me ha ayudado mucho. Tengo en uso varios componentes tuyos y la verdad es que me han servido muchísimo para aprender.

Eso que hace 10 años que programo en Delphi… uno nunca deja de aprender nuevas cosas no?

Lo único que agregaría, para perfeccionarlo es que hay que agregar al uses: Graphics y Controls ya que son usados por StringToColor y StringToCursor respectivamente.

De nuevo, muchas gracias.

2
0
Would love your thoughts, please comment.x
()
x