Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   OOP (https://www.clubdelphi.com/foros/forumdisplay.php?f=5)
-   -   Propiedad tipo Objeto (https://www.clubdelphi.com/foros/showthread.php?t=24953)

buildero_d 07-09-2005 18:50:14

Propiedad tipo Objeto
 
Que tal colegas,

Resulta que he creado un componente derivado de TListView, lo que intento es crear una nueva propiedad de tipo Objeto.... esta propiedad debe ser un apuntador a un Formulario.

Alguien me puede orientar para crear este tipo de propiedad.

Gracias anticipadas.:rolleyes:

dec 07-09-2005 19:05:19

Hola,

Si se trata de un formulario en concreto creo que tendrás que utilizar su tipo como tipo de la propiedad que precisas. Si no se trata de un formulario concreto podrías utilizar el tipo "TForm", de donde derivan los formularios. Supongamos que tú quieres que la propiedad sea del tipo de un formulario conque cuentas en el proyecto, por ejemplo: "TMiFormulario", pues bien, de ese tipo habría de ser la propiedad en cuestión. No sé hasta qué punto, si quisieras utilizar el tipo "TMiFormulario" bastaría con declarar la propiedad de tipo "TForm" y hacer uso después del polimorfismo.

buildero_d 07-09-2005 19:20:39

Gracias por la respuesta, amplio un poco mas la duda.

El formulario que quiero ligar al componente esta en mi proyecto, aunque no siempre será el mismo.

Este es mi codigo para crear la propiedad...

Código:

private:
                  Forms::TForm *FForm;
                  void __fastcall SetForm(Forms::TForm* aValue);
  protected:
  public:
 
  __published:
                  __property Forms::TForm* Form = {read=FForm, write=SetForm};

En el .cpp tengo la implementacion de la función SetForm
Código:

  void __fastcall TMiControl::SetForm(Forms::TForm* aValue)
  {
                  FForm = new Forms::TForm(aValue);
  }

En el inspector de objetos puedo ver mi nueva propiedad de mi componente, pero al momento de asignarle un form en el Inspector de Objetos me marca el error "Invalid property value"

¿Por qué no me deja asignarlo?... ¿debo de hacer algo adicional?

Saludos.

jmariano 07-09-2005 20:46:47

No conozco mucho el C++ Builder, pero me parece que estás asignando mal la propiedad en el método "Set". ¿No podrías hacer simplemente esta asignación: FForm = aValue?

Es decir, lo que tienes que conseguir es que la variable FForm "apunte" a la misma dirección dada por el parámetro (y me parece, si no estoy equivocado, que lo que estás haciendo es inicializar incorrectamente una nueva instancia del puntero pasado como parámetro, que, en tal caso, creo que sería así: FForm = new aValue).

(Tambien puede ser que esté diciendo una burrada! pero, como ya dije, no conozco mucho C++ Builder, de todas formas existe un foro donde te podrán ayudar mas: http://www.clubdelphi.com/foros/forumdisplay.php?f=13)

Saludos!

dec 07-09-2005 21:02:50

Hola,

Yo estoy como jmariano, que C++ me es bastante desconocido. Llevo desde que te contesté por vez primera tratando de hacer algo similar en Delphi, porque creo que no te sería complicada la traducción del código fuente a C++.

El caso es que no he conseguido lo que se proponía sino dando cierto rodeo que no sé hasta qué punto será necesario. He hecho varias pruebas, como te digo, y, en ninguna de ellas conseguía asignar un formulario a la propiedad de marras, salvo programáticamente, esto es, fuera del Inspector de objetos.

A lo último que he llegado ha sido a lo que a continuación expondré (el código fuente) y, de este modo, sí que he podido asignar un formulario a una propiedad de "mi componente" desde el Inspector de Objetos. Solo que lo que hago es asignar el formulario a una propiedad de una propiedad...

Me explicaré, se trata de dos clases: una de ellas contiene una propiedad a la cual puede asignársele un formulario. Esta misma clase es el tipo de una propiedad de "mi componente", de ahí que diga que he dado un rodeo que no sé hasta qué punto sería preciso dar, si supiera hacerse de otro modo.

En fin, aquí está el código fuente que digo que consigue al cabo hacer algo parecido a lo que se precisaba, si no es ya que todo ello sea deshechable porque no es exactamente lo que se pretendía realizar. El caso es que, como digo, al cabo puedo, mediante el Inspector de Objetos, asignar un formulario a una propiedad de "mi componente".

Como verás es código fuente de Delphi... espero que no tengas muchos problemas para traducirlo a código fuente de C++.

Código Delphi [-]
 unit UPruebas;
 
 interface
 
 uses
   Forms, Classes;
 
 type
   TMiForm = class(TPersistent)
   private
     FForm: TForm;
   public
     procedure Assign(Source: TPersistent); override;
   published
     property MiForm: TForm read FForm write FForm;
  end;
 
 type
   TMiComponente = class(TComponent)
   private
     FMiForm: TMiForm;
     procedure SetForm(Value: TMiForm);
   public
     constructor Create(AOwner: TComponent); override;
     destructor Destroy; override;
   published
     property MiForm: TMiForm read FMiForm write SetForm;
   end;
 
 procedure Register;
 
 implementation
 
 procedure Register;
 begin
   RegisterComponents('Samples', [TMiComponente]);
 end;
 
 { TMiComponente }
 
 constructor TMiComponente.Create(AOwner: TComponent);
 begin
   inherited Create(AOwner);
   FMiForm := TMiForm.Create;
 end;
 
 destructor TMiComponente.Destroy;
 begin
   FMiForm.Free;
   inherited;
 end;
 
 procedure TMiComponente.SetForm(Value: TMiForm);
 begin
   if Value <> FMiForm then
     FMiForm.Assign(Value);
 end;
 
 { TMiForm }
 
 procedure TMiForm.Assign(Source: TPersistent);
 begin
   inherited;
    if Source is TForm then
    begin
      FForm := TForm(Source);
    end;
    inherited Assign(Source);
 end;
 
 end.

buildero_d 07-09-2005 21:08:03

Muchas gracias por sus respuestas, seguire investigando, aunque creo que la duda en general es ¿Como crear una propiedad de tipo Objeto especificamente en TForm?, ya sea en Delphi o en C++ Builder.

Posteare en el foro que me has indicado.

Saludos y gracias.

dec 07-09-2005 21:15:08

Hola,

Mi gozo en un pozo, se suele decir en estos casos. ¡Pues no resulta que puedo asignar desde el Inspector de Objetos un formulario a la propiedad del componente pero no otro formulario! Me explico. Tengo dos unidades en el proyecto en que hago pruebas. Cada una de ellas representan formularios: "Form1" y "Form2".

Pues bien, puedo asignar desde el Inspector de Objetos, como digo, a la propiedad "MiForm" el formulario "Form1", pero, a la que trato de asignar a dicha propiedad "Form2" obtengo un "Invalid property value" muy bonito, en un diálogo con su icono de error y todo. ;)

Decididamente, no aprende uno y se mete no ya donde no le llaman, pero de donde es probable que no sepa salir... He probado a añadir el componente conque estoy probando también en el formulario "Form2" y ahí sí puedo añadir este a la propiedad del componente que se supone puede albergar variables del tipo "TForm"...

Esto de suponer... es mucho suponer... De todos modos hay algo que me extrañó de tu primer mensaje: comprendería que un formulario tuviera un objeto "TListView" en su interior, pero, ¿para qué necesitas que un "TListView" tenga "en su interior" un formulario?

roman 07-09-2005 21:24:58

Cita:

Empezado por dec
Código Delphi [-]
 procedure TMiForm.Assign(Source: TPersistent);
 begin
   inherited;
    if Source is TForm then
    begin
      FForm := TForm(Source);
    end;
    inherited Assign(Source);
 end;

Hola dec,

El propósito de Assign es copiar el contenido de un objeto a otro.

Cuando asignas

FForm := TForm(Source);

no estás copiando el contenido sino simplemente la referencia al objeto. Es decir que sólo has pospuesto el problema de la asignación en el método Set al método Assign.

Estoy seguro que ahora ya te queda claro. :)

// Saludos

roman 07-09-2005 21:28:00

Cita:

Empezado por dec
hay algo que me extrañó de tu primer mensaje: comprendería que un formulario tuviera un objeto "TListView" en su interior, pero, ¿para qué necesitas que un "TListView" tenga "en su interior" un formulario?

Bueno, a como veo las cosas, buildero_d no mencionó que quisiera un formulario contenido en el ListView, sólo dijo que un apuntador a él. Esto es, creo que sólo quiere guardar una referencia a otro formulario.

// Saludos

dec 07-09-2005 21:34:38

Hola,

Llevas razón en los dos mensajes que publicaste antes roman. Y otra vez digo que me metí en donde no debí, porque quien sabe, sabe, y ya se ve que yo no sé. Respecto de tu penúltimo mensaje, sí, comprendo que lo que estaba haciendo no era, precisamente, copiar, sino solamente asignar la referencia a otro objeto, que no es lo que se pretende con el método "Assing".

Lo que ocurre es que me pierdo, entonces. Quiero decir, ¿habría entonces que hacer algo como lo siguiente? Va a ser que no, pero, ¿qué tal parece esto? ¿Mejor que lo anterior?

Código Delphi [-]
  procedure TMiForm.Assign(Source: TPersistent);
  begin
    inherited;
     if Source is TForm then
     begin
       FForm.Assign(Source);
     end;
     inherited Assign(Source);
  end;

buildero_d 07-09-2005 21:34:57

Hola,

Trataré de traducir el código a C++ Builder.

Cita:

Pues bien, puedo asignar desde el Inspector de Objetos, como digo, a la propiedad "MiForm" el formulario "Form1", pero, a la que trato de asignar a dicha propiedad "Form2" obtengo un "Invalid property value" muy bonito, en un diálogo con su icono de error y todo. ;)
¡EXACTO! Creo que hemos hecho las mismas pruebas.... a mi me pasó lo mismo....

Cita:

¿para qué necesitas que un "TListView" tenga "en su interior" un formulario?
Te explico. Mas que tener un form en el "interior" de un TListView es tener una apuntador a un formulario (que no siempre será el mismo). Lo trato de hacer de esta manera para "automatizar" ciertas tareas comunes.

En mi caso el propósito de la propiedad MiForm me servirá para mostrar ese form al ejecutar cierta accion... (digamos al hacer doble clic sobre algun elemento del ListView).

Entonces lo que trato de hacer es apuntar hacia cierto formulario y despues mostrarlo dependiendo de ciertas acciones, pero esto a tráves de la propiedad MiForm... de esta forma simplifico las tareas y solo tengo que ligar algun form a mi componente y listo.

!Bueno al menos eso es lo que intento hacer!.

Saludos.

dec 07-09-2005 22:06:45

Hola,

Cita:

Empezado por buildero_d
Mas que tener un form en el "interior" de un TListView es tener una apuntador a un formulario (que no siempre será el mismo).

Sí; llevas razón. No se trata de que un "TListView" contenga un formulario. Después de ver lo que quieres conseguir, lo que se me ocurre es prescindir del Inspector de Objetos, esto es, una propiedad, en lugar de "published", "public", de tal manera que tendrías que asignarle un formulario mediante código, pero, en vista de los inconvenientes y que esto último parece funcionar... ¿qué te parece? No es una respuesta a la cuestión, pero, puede ser una solución, ¿no?...

roman 07-09-2005 23:22:44

Busquen el apartado How can I publish a property of type T[Custom]Form? en gexperts.

// Saludos

dec 08-09-2005 01:48:34

Hola,

Lo único que me queda claro (o es lo que me esfuerzo para que me quede claro) es que publicar (de modo que pueda editarse en el Inspector de Objetos) una propiedad de tipo "TForm" es, cuando menos, problemático.

Así que habría que publicarla de tipo "string" o similar (?) de manera que fuera la que albergara el nombre de la clase del formulario que nos interese, para luego utilizar una función como "GetClass" para poder trabajar con esta.

Desde luego buscando en Google no parecen encontrarse muchas (por no decir ninguna concreta y que sirva para lo que nos ocupa) referencias al asunto de publicar una propiedad de tipo "TForm" manipulable desde el Inspector de Objetos.

¿Alguien saca algo más en claro del texto que roman ha enlazado más arriba? Definitivamente hay días que mejor no haberse levantado uno de la cama, como suele decirse. Así que, como ya va siendo hora, voy a hacer como si no me hubiera levantado echándome de nuevo a leer un rato, por lo menos, a ver si se me levanto con otro pie.

buildero_d 08-09-2005 16:43:02

Que tal Dec,

Efectivamente, estoy de acuerdo contigo. Al parecer es algo no muy sencillo de hacer, y hasta puede que no sea posible.

La propuesta de publicar la propiedad de tipo string creo que pueda ser la solución, y explicare por que.

Esta explicación esta basada en un componente que esta incluido en la suite de componentes de "ABC for Delphi" (en su versión para C++ Builder).

Bien pues resulta que tiene un componente llamado "abcFormTabControl", dicho control te permite crear varias "pestañas" y en cada una de ellas puedes mostrar un formulario. La forma en como se hace la referencia al formulario es a través de una propiedad llamada Forms, que no es mas que una lista de los forms que te interesan presentar en cada una de las pestañas.

Se deduce que al tener solamente el nombre del formulario se crea una instancia del mismo.

Hice algunas pruebas al respecto y me encontre que al especificar un nombre de formulario no valido (por ejemplo MiForm) la aplicación envia el mensaje "Class TMiForm not found". Es decir hace uso de la función FindClass para verificar si la clase esta registrada.

En conclusión la forma de poder trabajar con forms haciendo referencia a ellos (en mi caso desde un componente personalizado) es a tráves del nombre del formulario.

Ahora en lo que me he enfocado es en averigüar ¿cómo crear la instancia de un form a través del nombre del formulario?, es decir, que con la propiedad de tipo string que me indica el nombre, poder crear y descargar el form. Esto puede ser menos complicado que lo anterior pero en este momento no sé como hacerlo.

Saludos.

roman 08-09-2005 17:11:22

Cita:

Empezado por buildero_d
Ahora en lo que me he enfocado es en averigüar ¿cómo crear la instancia de un form a través del nombre del formulario?, es decir, que con la propiedad de tipo string que me indica el nombre, poder crear y descargar el form. Esto puede ser menos complicado que lo anterior pero en este momento no sé como hacerlo.

En efecto, esto es sencillo:

Código Delphi [-]
// FormClassName es el nombre de la clase del formulario

var
  FormClass: TPersistentClass;

begin
   // Ver si el formulario está registrado
   FormClass := FindClass(FormClassName);

  // Ver que realmente sea un descendiente de TForm
  if FormClass.InheritsFrom(TForm) then
    // Crear el formulario y mostrarlo
    with TFormClass(FormClass).Create(Application) do
      Show;

Para que esto funcione debes registrar previamente la clase del formulario con RegisterClass o RegisterClasses. Lo más cómodo es hacerlo en la sección initialization de la unidad del formulario.

// Saludos

buildero_d 09-09-2005 00:01:55

Hola,

Pues muchas gracias por su ayuda, al fin en conseguido lo que necesitaba (claro traduciendo el codigo a C++ Builder :p) y va de maravilla. Sus aportaciones me ampliaron mucho el panorama. :cool:

En definitiva la opción que tomé fue la de la propiedad tipo string para generar la instancia del form.

Un saludo y nuevamente, gracias.


La franja horaria es GMT +2. Ahora son las 11:53:50.

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