É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:
// 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 (simpre 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
porpiedades -TStrings-).
{: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 utilizaión podría ser el siguiente:
(basta con un formulario que tenga un TButton y un TMemo)
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;
Indice