PDA

Ver la Versión Completa : Buscar componentes de un formulario usando rtti


juank1971
22-03-2023, 20:18:36
saludos como puedo buscar todos por ejemplo los TstringGrids de un formulario usando rtti ?

algo por ejemplo como esto

for i := 0 to Formulario.ComponentCount - 1 do
begin
if Formulario.Components[i].ClassName= 'TStringGrid' then
begin
Grid := TStringGrid(Formulario.Components[i]); // encontró alguno
if Grid.ColumnCount > 0 then // comprueba que tenga columnas
try
......................................

quisiera hacer esto con rtti, he tratado de buscar en google y clubdelphi pero todos los ejemplos buscan propiedades y demas de las clases no instanciadas.

o por ejemplo esto otro quisiera tambien hacerlo con RTTI:


function GetLinkGridToDataSource(Formulario: TForm; Grid: string): TLinkGridToDataSource;
var
l:TLinkGridToDataSource; s:TStringGrid;
begin
result := nil;
for var i := 0 to Formulario.ComponentCount - 1 do
if Formulario.Components[i] is TLinkGridToDataSource then
begin
l:= Formulario.Components[i] as TLinkGridToDataSource;
if l.GridControl is TStringGrid then
begin
s:= l.GridControl as TStringGrid;
if Grid = s.name then
result := l;
end;
end;
end;

Neftali [Germán.Estévez]
23-03-2023, 09:27:33
como puedo buscar todos por ejemplo los TstringGrids de un formulario usando rtti ?


La forma de hacerlo es utilizando FindComponent de forma similar a como se ve en el código; Mejor usando IS que la comparación por ClassName.
Este recorrido es lento. Si necesitas hacerlo mçás de una vez, puedes almacenar los componentes en una Lista (TObjectList) para no tenerlo que hacer más de una vez.

Otra opción es crear manualmente esa lista al crear el formulario.


Memo1.Lines.Clear;
for var i:integer := 0 to ComponentCount - 1 do
if Components[i] is TStringGrid then
Memo1.Lines.Add(Components[i].Name + ' -> ClassName:' + Components[i].ClassName);


Este código funciona tanto para VCL como para FMX.
Para buscar otros componentes como el que comentas (clase TLinkGridToDataSource) basta adaptar ese código para la nueva clase.


for var i:integer := 0 to ComponentCount - 1 do
if Components[i] is TLinkGridToDataSource then
Memo1.Lines.Add(Components[i].Name + ' -> ClassName:' + Components[i].ClassName);

En cuanto a esta cabecera:

function GetLinkGridToDataSource(Formulario: TForm; Grid: string): TLinkGridToDataSource;

En estos casos es mejor pasar directamente los componentes, no los nombres (parea no tener que realizar las búsquedas).

function GetLinkGridToDataSource(Formulario:TForm; Grid: TStringGrid): TLinkGridToDataSource;

Con una implementación similar a esta:

function GetLinkGridToDataSource(Formulario:TForm; Grid: TStringGrid): TLinkGridToDataSource;
begin
Result := nil;
for var i:integer := 0 to Formulario.ComponentCount - 1 do
if Formulario.Components[i] is TLinkGridToDataSource then begin
var comp:TComponent := Formulario.Components[i];
if Assigned(TLinkGridToDataSource(comp).GridControl) then
if (TLinkGridToDataSource(comp).GridControl = Grid) then begin
Result := TLinkGridToDataSource(comp);
Exit;
end;
end;
end;

Neftali [Germán.Estévez]
23-03-2023, 09:43:53
Si aplicamos el último procedimiento al primero que hemos usado para buscar los TStringGrids, podríamos hacer algo como eso:

procedure TForm4.Button1Click(Sender: TObject);
begin
Memo1.Lines.Clear;
for var i:integer := 0 to ComponentCount - 1 do
if Components[i] is TStringGrid then begin
var lds: TLinkGridToDataSource := GetLinkGridToDataSource(Self, TStringGrid(Components[i]));
if Assigned(lds) then
Memo1.Lines.Add('Grid: ' + Components[i].Name + ' tiene asignado LinkDS: ' + lds.Name)
else
Memo1.Lines.Add('Grid: ' + Components[i].Name + ' no tiene asignado LinkDS');
end;
end;

juank1971
23-03-2023, 13:16:24
que bien gracias , no hay necesidad de usar rtti entonces.
rtti a mi modo de ver al parecer es mas bien cuando quiero cambiar propiedades e run time
como por ejemplo esta función para habilitar los componentes de un Tlayout al editar,
ahora estoy recordando ver una función para algo de esto en tu blog neftali.

procedure HabilitarComponentes(LY: TLayout; Hab: boolean);
begin
with LY do
for var i := 0 to ControlsCount - 1 do
begin
if Controls[i] is TEdit then
(Controls[i] as TEdit).CanFocus := Hab;

if Controls[i] is TMemo then
(Controls[i] as TMemo).CanFocus := Hab;

if Controls[i] is TDateEdit then
(Controls[i] as TDateEdit).CanFocus := Hab;

if Controls[i] is TcomboBox then
(Controls[i] as TcomboBox).Enabled := Hab;
end;
end;

Neftali [Germán.Estévez]
23-03-2023, 15:06:52
como por ejemplo esta función para habilitar los componentes de un Tlayout al editar,
ahora estoy recordando ver una función para algo de esto en tu blog neftali.
Código Delphi [-] (https://www.clubdelphi.com/foros/#)procedure HabilitarComponentes(LY: TLayout; Hab: boolean); begin with LY do for var i := 0 to ControlsCount - 1 do begin if Controls[i] is TEdit then (Controls[i] as TEdit).CanFocus := Hab; if Controls[i] is TMemo then (Controls[i] as TMemo).CanFocus := Hab; if Controls[i] is TDateEdit then (Controls[i] as TDateEdit).CanFocus := Hab; if Controls[i] is TcomboBox then (Controls[i] as TcomboBox).Enabled := Hab; end; end;



Es posible.
Justo para evitar código como el que muestras ahí, es para lo que va muy bien usar RTTI.