Acceder a las propiedades de un componente vía RTTI
É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; |


