Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   OOP (https://www.clubdelphi.com/foros/forumdisplay.php?f=5)
-   -   Cómo modificar las propiedades de una clase en Runtime antes de ser instanciada (https://www.clubdelphi.com/foros/showthread.php?t=93529)

juniorSoft 28-10-2018 13:34:36

Cómo modificar las propiedades de una clase en Runtime antes de ser instanciada
 
Hola nuevamente amigos,

Les planteo lo que deseo realizar:

Tengo un método para realizar tareas de modificación de reportes (fastReport) que están en distintos contenedores ya sean formularios o módulos de datos, dichos contenedores son creados en ejecución y la intensión es que estos contenedores solo estén creados no que sean visibles, lo único visible sera el diseñador de fastReport para modificar el reporte en ejecución.

les muestro aquí el código realizado

Código Delphi [-]
procedure TMDConfigReportes.ModificarReporte(ClassCReport: TComponentClass;
  NombreReporte: string);
var
  Rep:TFrxReport;
  RutaRep:string;
begin
  with ClassCReport.Create(Self) do
    begin
      try
         Rep:=TFrxReport(FindComponent(NombreReporte));

         RutaRep:=ExtractFilePath(GetModuleName(HInstance))+Rep.EngineOptions.TempDir;
         if FileExists(RutaRep) then
           Rep.LoadFromFile(RutaRep)
         else
           raise Exception.Create('No se encontro el reporte en el directorio '+RutaRep);
          Rep.DesignReport(True);
      finally
         Free;
      end;
    end;
end;


En el caso de los Módulos de datos no hay inconvenientes ya que no son visibles, pero los formularios se visualizan una vez creados.

una solución seria asignar la propiedad visible de los formularios a false y luego en el método show del formulario ponerlo a true, pero esto me trae otras consecuencias para algunos detalles de visualización, ademas tendría que modificar la clase base para que todos los formularios que hereden realicen el mismo comportamiento.

y la idea que tengo es, aunque no se implementarla sospecho que con RTTI puedo hacer algo como sigue para asignar la propiedad visible de la clase de formulario a false solo para acceder a los componentes de reportes, pero me falta el detalle mas importante

Código Delphi [-]
if ClassCReport.InheritsFrom(TForm) then
  begin
      //cambiar la propiedad visible a la clase del formulario
  end; 
  ....

//luego se crearía el objeto del formulario o modulo de datos para acceder a los reportes y evitaría el efecto de que se muestre si es un formulario aunque sea por segundos, porque ya con la instancia si puedo acceder a la propiedad visible pero el efecto anterior no es el deseado.


Saludos,

juniorSoft 30-10-2018 12:33:07

El titulo mas bien debería decir: Como modificar las propiedades de una clase en Runtime antes de ser instanciada

Varias ideas que se me han ocurrido pero cuando lo analizo bien no doy con la solución:

1-Heredar de la clase y crearle un constructor para inicializar la propiedad visible a false.

El problema es que al ser un parámetro de referencia de clase no se de antemano cual es la clase que se pasará y no se como heredar en runtime de la clase pasada como parámetro.

2-Utilizar una Class Helpers, pero estas no soportan un constructor.

3- Utilizar los métodos ReadComponentResFile y WriteComponentResFile para modificar los dfm, esta idea no me gusta mucho.

Neftali [Germán.Estévez] 30-10-2018 17:01:39

Tal vez no lo he entendido bien, pero creo que esto te daría True si en tu caso los elementos creados derivan de un TForm y False si derivan de un TDataModule.


Código Delphi [-]
   ...

    if ClassCReport.InheritsFrom(TForm) then
      Memo1.Lines.Add('FORMULARIO')
    else if ClassCReport.InheritsFrom(TDataModule) then
      Memo1.Lines.Add('DATAMODULE');

juniorSoft 30-10-2018 17:59:51

Hola Nefttali

Disculpa si no lo he descrito bien.

Lo que sucede es que los formularios por defecto tienen la propiedad Visible = True y al utilizar ClassCReport.Create(Self) se muestran inmediatamente antes de hacer cualquier cosa, y lo que deseo evitar es que se haga un parpadeo al mostrarse por unos segundos el formulario antes de mostrar el diseñador de reportes porque luego con la instancia ya los puedo poner invisible. Este método es genérico para modificar los reportes que estén contenidos tanto en módulos de datos como en formularios y que dichos reportes dependen de los dataset u otros componentes asociados que están contenidos también en dichos módulos de datos o formularios.

Para ello cree este método genérico que pasandole la clase de un Modulo de datos o un formulario lo instancia y el nombre del reporte que deseo modificar.

Los reportes están guardados en un directorio y los ubico utilizando una ruta que les asigno en la propiedad .EngineOptions.TempDir del frxReport en cuestión.

Como más arriba explique puedo cambiar en modo diseño la propiedad visible de los formularios a false pero es que esta instanciación con los formularios invisibles solo la necesito para configurar los reportes y guardar su modificación todo en runtime. y si lo hago de esta manera entonces tengo inconvenientes cuando voy a utilizar los formularios para la función que están definidos por que hago ciertos procesos en el método show del formulario que aunque ponga la propiedad visible de nuevo antes de hacer dichos procesos, estos no realizan el trabajo como antes.



Saludos,

juniorSoft 30-10-2018 18:11:12

Por ejemplo con RTTI he visto ejemplos y lo he adaptado pero RTTI se aplica a la instancia de la clase no a la clase

Código:

procedure TMDConfigReportes.FormInvisible(ClassCReport: TComponentClass);
var
  VCtx : TRttiContext;
  VType: TRttiType;
  VProp: TRttiProperty;

begin
  VCtx := TRttiContext.Create;
  try
    VType := VCtx.GetType(ClassCReport);
    VProp := VType.GetProperty('Visible');
    VProp.SetValue(ClassCReport, False); //Aquí daría un error de memoria porque ClassCReport es una clase no una instancia de una clase

  finally
      VCtx.Free;
  end;
end;


Neftali [Germán.Estévez] 31-10-2018 10:09:31

Tal como comentas, la propiedad no se puede modificar en una referencia a clase sino en una instancia.
El código que te había puesto era para utilizarlo justo después de realizar el Create (de la instancia).

juniorSoft 31-10-2018 12:07:57

Cita:

Tal como comentas, la propiedad no se puede modificar en una referencia a clase sino en una instancia.
El código que te había puesto era para utilizarlo justo después de realizar el Create (de la instancia).
Ok, pero en realidad no saber si es un Form o un DataModule después de instanciada la clase ya que el efecto se ha dado, el error aunque no tan grave es que solo con el create de un form sin hacer show este se visualiza y produce la visualización del formulario antes de poder ponerlo invisible que con los datamodules esto no ocurre por su naturaleza.

A Delphi cuando no se le especifica a un formulario explicitamente la propiedad visible a false este no la crea en su archivo DFM y en realidad aunque pueda tener acceso a modificar la clase tendría que crear la propiedad e igualarla a false.

De todas formas no es tan grave el efecto.

Saludos,


La franja horaria es GMT +2. Ahora son las 06:00:55.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi