PDA

Ver la Versión Completa : Creacion componente


CHiCoLiTa
05-09-2005, 18:42:40
Hola, que tal?

Como puedo crear una serie de propiedades en un componente en donde aparezca un '+' y al pinchar se despliegue las propiedades

Es para tenerlo todo un poco ordenado por categorias y que no aparezcan un monton de cosas en el inspector de objetos desordenadas y que luego no te enteras de que es cada cosa

Supongo que es muy facil :cool: , pero nunca lo he hecho y no he encontrado nada

Gracias

dec
05-09-2005, 18:58:17
Hola,

Tienes que añadir al componente en cuestión una propiedad ("published", para que aparezca en el Inspector de Objetos) de un determinado tipo que a su vez incluya determinadas propiedades. De este modo conseguirás lo que persigues. Puedes fijarte en componentes que tengan lo que quieres tenga el tuyo, verás que no es complicado.

Aldo
05-09-2005, 19:06:50
Hola Chicolita:

Vamos a ver. Eso que quires hacer es fácil como dices. Solo debes crear en tu componente principal propiedades que sean a su vez otros componentes heredados de un TPersistent. Es decir Supongamos que estás creando un componente que tendrá una propiedad que se llame Layout y esta a su vez se compone de otras propiedades individuales que son Left, Top, Height, Width.

En este caso creas un componente que herede de TPersistent ( Ej TLayout ) que contenga las cuatro propiedades antes mencionadas y en tu componente principal creas una propiedad del tipo TLayout

Un ejemplo de código


TLayout = Class( TPersistent )
private
FLeft : Integer;
{...}
FWidth : Integer;
public
{...}
protected
{...}
published
property Left : Integer read FLeft write FLeft;
property Width : Integer read FWidth write FWidth;
end;

TMyComponent = Class( TComponent )
private
FLayout : TLayout;
public
protected
published
property Layout : TLayout read FLayout write FLayout;
end;

Espero que te haya ayudado en lo que querías hacer.

Un saludo Aldo

dec
05-09-2005, 19:31:49
Hola,

Pues yo voy a reconocer que he preparado un pequeño ejemplo basándome en mi primera idea, que había cogido de ver los componentes que implementan propiedades de la forma que estamos refiriendo en este Hilo. Pues bien, primero hize algo muy similar a lo que Aldo ha propuesto, pero, aunque podía ver el símbolo "+" en la propiedad correspondiente en el Inspector de Objetos... era como si no estuviera, porque no desplegaba la lista de propiedades tal como esperaba.

Luego me fijé en cómo se hace en la clase "TControl", concretamente en su propiedad "Constraints", de tipo "TSizeConstraints", que es una propiedad que puede verse también (heredada de "TControl") en los "TForm", sin ir más lejos... la forma en que se lleva a cabo en dicha propiedad es algo más elaborada que lo que intenté la vez primera, pero, aunque conseguir implementar algo parecido en el componente de pruebas que estaba llevando a cabo para lograr lo que CHiCoLiTa seguía teniendo el mismo inconveniente... La propiedad aparece en el Inspector de Objetos, pero la "+" a su izquierda no sirve de mucho, porque no funciona...

En fin, me declaro inútil, creo que habría que investigar un tanto más el asunto, o que en algo metí la pata y no sé ahora mismo en qué puede haber sido... así que si antes dije que la cosa no era "complicada", ahora retiro lo dicho, y pido disculpas, pues que creo que pequé de hablador, siendo que no es tan sencillo como parece, o que, no puedo decir yo que lo sea cuando no he podido llevarlo a cabo ni a la de tres...

dec
05-09-2005, 19:48:53
Hola,

Bueno. Pues ya parece que puedo decir que no era tan complicado. Al cabo faltaba la creación de la clase que se utiliza en el componente y que es la que contiene las propiedades que hay que mostrar bajo el símbolo "+" en el Inspector de Objetos. Esto y alguna otra cosa, porque he añadido algunas hasta dar con el secreto. Con el permiso de Aldo, observa, CHICoLiTa, el siguiente código, por si puede ayudarte en algo:


{
Corregido tendiendo en cuenta
lo dicho por roman más abajo
}

unit UPruebas;

interface

uses
Classes;

type
TPruebas = class(TPersistent)
private
FAlto: integer;
FAncho: integer;
public
procedure Assign(Source: TPersistent); override;
published
property Alto: integer read FAlto write FAlto default 0;
property Ancho: integer read FAncho write FAncho default 0;
end;

type
TDePruebas = class(TComponent)
private
FPruebas: TPruebas;
procedure SetPruebas(Value: TPruebas);
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property Pruebas: TPruebas read FPruebas write SetPruebas;
end;

procedure Register;

implementation

procedure Register;
begin
RegisterComponents('Samples', [TDePruebas]);
end;

{ TDePruebas }

constructor TDePruebas.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FPruebas := TPruebas.Create;
FPruebas.Alto := 0;
FPruebas.Ancho := 0;
end;

destructor TDePruebas.Destroy;
begin
FPruebas.Free;
inherited Destroy;
end;

procedure TDePruebas.SetPruebas(Value: TPruebas);
begin
if Value <> FPruebas then
Value.Assign(FPruebas);
end;

{ TPruebas }

procedure TPruebas.Assign(Source: TPersistent);
begin
if Source is TPruebas then
begin
FAlto := TPruebas(Source).FAlto;
FAncho := TPruebas(Source).FAncho;
end;
inherited Assign(Source);
end;

end.

CHiCoLiTa
05-09-2005, 19:55:06
Nos esta faltando el constructor del componenete para que en la clase TPersisten se puedan crear el 'desplegable'.
Voy a ver si me sale y comento la solucion final

CHiCoLiTa
05-09-2005, 20:01:50
Vaya, he llegado tarde por unos minutos
dec ha puesto justo lo que faltaba
Sobretodo muchisimas gracias a Aldo
Una cosita mas que se hacer

roman
05-09-2005, 20:02:21
Nada más un detalle respecto del ejemplo de dec. La clase contenedora se encarga de la construcción y destrucción del objeto Pruebas, es decir, le pertenece. Por tanto hay que proteger la propiedad contra cambios no deseados: si se asigna

DePruebas.Pruebas := ObjetoPruebas

estamos sustituyendo el objeto que originalmente pertenecía a DePruebas por otro y al hacer FPruebas.Free será este otro el que estemos destruyendo y el objeto original se habrá quedado atorado en memoria.

Normalmente, para este tipo de propiedades hay que definir un método set:


property Pruebas: TPruebas read FPruebas write SetPruebas


donde SetPruebas se encargará de copiar el contenido. Puede hacerlo campo por campo aunque lo usual es transferir ese copiado al método Assign de TPruebas:


type
TPruebas
public
procedure Assingn(Source: TPersistent); override;
end;


y dejar SetPruebas con:

FPruebas.Assign(Value);

// Saludos

dec
05-09-2005, 20:24:48
Hola,

roman, me queda una duda, ¿viste que edité el código fuente para añadir el método "SetPruebas" tal como decías? Ahora bien, en donde se lee el comentario "{ ¿Acaso falta algo que hacer aquí? }"... ¿hay, efectivamente, que hacer algo más?

Actualización: Me temo que sí que había que hacer algo... claro está... creo que con lo siguiente sería bastante, y si me equivoco aquí estoy para que se me diga en qué. ;) Y en todo caso muchas gracias roman.


{ TPruebas }

procedure TPruebas.Assign(Source: TPersistent);
begin
if Source is TPruebas then
begin
FAlto := TPruebas(Source).Alto;
FAncho := TPruebas(Source).Alto
end;
inherited Assign(Source);
end;