Inicio > Delphi, Trucos > Acceder a las propiedades de un componente vía RTTI

Acceder a las propiedades de un componente vía RTTI

Jueves, 8 de noviembre de 2007 Dejar un comentario Ir a comentarios

Éste truco aparece debido a la necesidad de obtener vía RTTI la siguiente información: Lista de todas las propiedades de un componente.

Valor de una propiedad de un componente sin utilizar el método siguiente (*).
Una primera aproximación para obtener la propiedad (Left, por ejemplo) de un componente del que a priori no conocemos el tipo, es utilizar una estructura IF o CASE (método 1) similar a la siguiente:

1
2
3
4
5
6
7
8
// Metodo 1 (*)
// Segun el tipo de componente...
if (comp is TEdit) then
  Result := TEdit(comp).Left;
else if (comp is TLabel) then
  Result := TLabel(comp).Left;
else if (comp is TButton) then
  Result := TButton(comp).Left;

Está claro que éste método es poco eficiente, poco flexible (siempre podemos dejarnos algún tipo de componente) y poco ortodoxo.
¿Cómo debe hacerlo Delphi para mostrar las propiedades de un componente en el inspector de objetos (por ejemplo)?

La respuesta es RTTI. Se puede acceder a las propiedades de un componente (a partir de la clase) y del nombre de la propiedad, utilizando la siguiente función (he añadido un parámetro nuevo para obtener en la misma llamada la lista de todas las propiedades -TStrings-).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
{:Obtener la información de una propiedad a partir de la clase y el nombre;
Ademas devuelve la lista de todas las porpiedades de ese control.}
function GetRTTIControlInfo(AControl: TPersistent;
         propList:TStrings;  AProperty: string): PPropInfo;
var
   i: integer;
   props: PPropList;
   tData: PTypeData;
begin
   // Inicial
   Result := nil;
   // No asignado el control ==> Salimos
   if (AControl = nil) or (AControl.ClassInfo = nil) then begin
      Exit;
   end;
   // Obtener la información
   tData := GetTypeData(AControl.ClassInfo);
   // Tipo desconocido o sin propiedades ==> Salimos
   if (tData = nil) or (tData^.PropCount = 0) then
   	Exit;
    GetMem(props, tData^.PropCount * SizeOf(Pointer));
    try
   	GetPropInfos(AControl.ClassInfo, props);
 	for i := 0 to tData^.PropCount - 1 do begin
   		propList.Add(Props^[i]^.Name);
   		with Props^[i]^ do begin
    		  if (Name = AProperty) then begin
		   	result := Props^[i];
	   	  end;
   	        end;
   	end;
   finally
      FreeMem(props);
   end;
end;

Un ejemplo de utilización podría ser el siguiente:
(basta con un formulario que tenga un TButton y un TMemo)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
procedure TForm1.Button1Click(Sender: TObject);
var
  pInfo: PPropInfo;
  propList:TStrings;
  PStr:String;
begin
 // Crear la lista
 propList := TStringList.Create();
 // protección para liberar
 try
 
  // Acceder a la info de la propiedad
  pInfo := GetRTTIControlInfo(Button1, propList, 'Left');
  // La prop. encontrada es de tipo integer (debería ser, ya que es la
  // prop. Left)
  if (pInfo.PropType^^.Kind in [tkInteger]) then begin
    // Obtener
    PStr:= 'Left' + ' = ' + Format('%d', [GetOrdProp(Button1, pInfo)]);
    // Mostrar
    MessageDlg(PStr, mtInformation, [mbOK], 0);
  end;
  // Rellenar la lista de propiedades
  Memo1.Lines.Assign(propList);
 finally
    FreeAndNil(propList);
 end;
end;
Categories: Delphi, Trucos Tags: , , ,
  1. Sin comentarios aún.
  1. Sin trackbacks aún.
Escribe la palabra "humano" en el cuadro/Write the word "humano" in answer.
Please leave these two fields as-is:
IMPORTANTE! Para continuar, debes contestar la pregunta anterior (para evitar SPAM) :-)