Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > OOP
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 26-09-2005
lento manu lento manu is offline
Miembro
 
Registrado: oct 2004
Posts: 29
Poder: 0
lento manu Va por buen camino
Override eventos On...

Estoy intentando tener acceso a los eventos principales de un Form desde un componente que lo contiene, para poder sobrescribirlos al modo override o inherited.
La idea es disponer de un form de exploración DB tipo y convertirlo en componente. Pues bien, si yo llamo a este componente desde una Query, para editar los valores de algún dato en modo Tabla por ejemplo, y realizar un locate cuando el componente ha acabado su creación. Si accedo a la propiedad OnActivate, esta se sobrescribe sustituyendo, pero no complementando la original.
Este componente es parecido al TDBViewer del curso de Luis Roche, pero quiero que en inspector de objetos me aparezcan los eventos tales como: OnActivate, OnShow, OnClose, OnDestroy. Actualmente lo consigo, pero los métodos antecesores desparecen y no se ejecutan en 'inherited', es decir: en herencia después de lo declarado en los eventos originales.
¿Cómo puedo declarar estos eventos en mi componente de enlace?
Ya pego el código del compo para que lo probéis si queréis con cualquier Form al uso. Si queréis más código me lo pedís. ¿Vale?
El código imprescindible de la llamada del Componente en el form que creamos dinámicamente es:
Código Delphi [-]
public
constructor CreateTabla(aOwner:TComponent; data: TDataSet);
...
published
Tabla: TDataSet;
...
implementacion ...
constructor TfmExploracionTabla.CreateTabla(aOwner:TComponent; data: TDataSet);
begin
 
try
if data.Active then
abierta:= True
else
abierta:= False;
 
Tabla:= data;
if Tabla is TTable then
nombreTabla:= (Tabla as TTable).TableName;
if Tabla is TADOTable then
nombreTabla:= (Tabla as TADOTable).TableName;
except
begin
Destroy;
Raise;
end;
end;
 
inherited Create (aOwner);
 
end;
Jolines: Que bonitas quedan las etiquetas "Delphi".
Ahora el código del componente en si:
Código Delphi [-]
{$A+,B-,C+,D+,E-,F-,G+,H+,I+,J-,K-,L+,M-,N+,O+,P+,Q-,R-,S-,T-,U-,V+,W-,X+,Y+,Z1}
{$MINSTACKSIZE $00004000}
{$MAXSTACKSIZE $00100000}
{$IMAGEBASE $00400000}
{$APPTYPE GUI}
unit DBX;
interface
uses
Windows, Messages, SysUtils, Classes, Forms, DB, DBTables, DBGridCheck;
type
TDBexplorer = class(TComponent)
private
{ Private declarations }
FTable: TDataSet;
FModal: boolean;
FOnActivate: TNotifyEvent;
FOnShow: TNotifyEvent;
FOnDie: TNotifyEvent;
FOnClose: TCloseEvent;
FOnEndDock: TEndDragEvent;
function GetTable: TDataSet;
procedure SetTable (value: TDataSet);
 
protected
{ Protected declarations }
public
{ Public declarations }
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Execute;
published
{ Published declarations }
property Table: TDataSet read GetTable write SetTable;
property Modal: boolean read FModal write FModal default True;
//@J@// estos métodos se sobrescriben y no se ejecutan en TExControlsTabla
property OnActivate: TNotifyEvent read FOnActivate write FOnActivate;
property OnShow: TNotifyEvent read FOnShow write FOnShow;
property OnDie: TNotifyEvent read FOnDie write FOnDie;
property OnClose: TCloseEvent read FOnClose write FOnClose;
end;
 
procedure Register;
 
implementation
 
uses ExControlsTabla;
 
constructor TDBexplorer.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FModal := True;
end;
destructor TDBexplorer.Destroy;
begin
inherited Destroy;
end;
 
function TDBexplorer.GetTable :TDataSet;
begin
Result:= FTable;
end;
 
procedure TDBexplorer.SetTable(value: TDataSet);
begin
if FTable <> value then
begin
FTable:= Value;
if value <> nil then
value.FreeNotification(Self);
end;
end;
 
procedure TDBexplorer.Execute;
var
Explorador: TfmExControlsTabla;
begin
Explorador:= TfmExControlsTabla.CreateTabla(Owner, FTable);
//Ojo: para impedir acceder al código OnDestroy si el parent abre noModal
if Modal and (Owner<>nil) then
Explorador.OnDestroy:= OnDie;
//probando...
Explorador.OnClose:= OnClose;
Explorador.OnActivate:= OnActivate
Explorador.OnShow:= OnShow;
if FModal then
try
Explorador.ShowModal;
 
finally
Explorador.Free;
end
else
try
Explorador.Show;
except
Explorador.Free;
end;
end;
 
procedure Register;
begin
RegisterComponents('Data Controls', [TDBexplorer]);
end;
end.
¡¡Gracias a todos!!

Última edición por lento manu fecha: 05-10-2005 a las 17:57:36.
Responder Con Cita
  #2  
Antiguo 26-09-2005
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.323
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
¿Y si en Lugar de TComponent, derivas de TControl (que tiene esos eventos)?
__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.
Responder Con Cita
  #3  
Antiguo 26-09-2005
lento manu lento manu is offline
Miembro
 
Registrado: oct 2004
Posts: 29
Poder: 0
lento manu Va por buen camino
Probado:

Gracias, es una gran idea.

He hecho la prueba:
En el form desaparece el componente como icono y queda como un control invisible: única diferencia en diseño.
En ejecucíón pasa lo mismo. El código que debe ejecutarse en el form que contiene OnActivate, por ejemplo, se omite en espera de un nuevo código en el uso del compo ¡desprotejiendo así toda su codificación!
Responder Con Cita
  #4  
Antiguo 30-09-2005
lento manu lento manu is offline
Miembro
 
Registrado: oct 2004
Posts: 29
Poder: 0
lento manu Va por buen camino
Solución a Sobreescibir Eventos en Componentes

He encontrado una solución, que funciona, pero no he conseguido un override sobre el evento, ya que el componente que abre el form, es un simple Tcomponent, no tiene este mismo valor en herencia. Tampoco he conseguido un inherited. La llamada
Código Delphi [-]
Explorador:= TfmExControlsTabla.CreateTabla(Owner, FTable);
crea un Form que ha su vez es un inherited de otro inicial. Este form tiene en el OnActivate las llamadas, que generan controles DBtext, DBimage, DB... lo que sea. Estas llamadas se inician en el evento OnActivate.
Os pego el código porque creo os puede interesar (si veis algo mal, avisarme, por favor).
Código Delphi [-]
 
unit DBX;
interface
uses
Windows, Messages, Controls, SysUtils, Classes, Forms, DB,
DBTables,
DBGridCheck,
ExControlsTabla;
type
TEndDragEvent = procedure(Sender, Target: TObject; X, Y: Integer) of object;
TDBexplorer = class(TComponent)
private
{ Private declarations }
FTable: TDataSet;
FModal: boolean;
FOnActivate: TNotifyEvent;
FOnShow: TNotifyEvent;
FOnDie: TNotifyEvent;
FOnClose: TCloseEvent;
FOnEndDock: TEndDragEvent;
CloseAction: TCloseAction;
function GetTable: TDataSet;
procedure SetTable (value: TDataSet);
procedure Cerrar(var Action: TCloseAction);
procedure Activate(Sender: TObject);
protected
{ Protected declarations }
public
{ Public declarations }
Explorador: TfmExControlsTabla;
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Execute;
 
published
{ Published declarations }
property Table: TDataSet read GetTable write SetTable;
property Modal: boolean read FModal write FModal default True;
//@J@// estos métodos se sobrescriben y no se ejecutan en TExControlsTabla
property OnActivate: TNotifyEvent read FOnActivate write FOnActivate;
property OnShow: TNotifyEvent read FOnShow write FOnShow;
property OnDie: TNotifyEvent read FOnDie write FOnDie;
property OnClose: TCloseEvent read FOnClose write FOnClose;
property OnEndDock: TEndDragEvent read FOnEndDock write FOnEndDock;
end;
procedure Register;
implementation
//uses ExControlsTabla;
constructor TDBexplorer.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
// asignar las propiedades por defecto:
FModal := True;
end;
destructor TDBexplorer.Destroy;
begin
if Assigned (Explorador) then
FreeAndNil(Explorador);
inherited Destroy;
end;
 
function TDBexplorer.GetTable :TDataSet;
begin
Result:= FTable;
end;
 
procedure TDBexplorer.SetTable(value: TDataSet);
begin
if FTable <> value then
begin
FTable:= Value;
if value <> nil then
value.FreeNotification(Self);
end;
end;
 
procedure TDBexplorer.Execute;
//cambiado a public para poder escribir sobre evento OnActive desde el procedure Activate:
{
var
Explorador: TfmExControlsTabla;
}
begin
Explorador:= TfmExControlsTabla.CreateTabla(Owner, FTable);
//Ojo: para impedir acceder al código OnDestroy si el parent abre noModal
if Modal and (Owner<>nil) then
Explorador.OnDestroy:= OnDie;
Explorador.OnActivate:= Activate;
Explorador.OnClose:= OnClose;
Explorador.OnShow:= OnShow;
Explorador.OnEndDock:= OnEndDock;
 
if FModal then
try
Explorador.ShowModal;
 
finally
Explorador.Free;
end
else
try
Explorador.Show;
except
Explorador.Free;
end;
end;
 
procedure Register;
begin
RegisterComponents('Data Controls', [TDBexplorer]);
end;
 
procedure TDBexplorer.Cerrar(var Action: TCloseAction);
begin
inherited;
if Assigned(FOnClose) then FOnClose(Self, Action);
end;
 
procedure TDBexplorer.Activate(Sender: TObject);
begin
inherited;
if Assigned(Explorador) then
begin
//rellamamos los mismos procedidmientos que están declarados en el
//evento OnActivate del form Explorador:
Explorador.Crear(Sender);
Explorador.ColorIndices;
end;
end;
end.
Gracias por las ayudas recibidas. Espero que esto pueda servir para alguien.

Última edición por lento manu fecha: 05-10-2005 a las 17:59:15.
Responder Con Cita
  #5  
Antiguo 30-09-2005
[maeyanes] maeyanes is offline
Capo de los Capos
 
Registrado: may 2003
Ubicación: Campeche, México
Posts: 2.732
Poder: 24
maeyanes Va por buen camino
Lo que puedes hacer es crear unos campos privados en tu componente, del mismo tipo que los eventos que necesitas. Por ejemplo, el OnActivate:
Código Delphi [-]
private
  FOldOnActivate: TNotifyEvent;
Entonces al crear el formulario haces algo como:
Código Delphi [-]
FOldOnActivate := Explorador.OnActivate;
Explorador.OnActivate:= Activate;

Y en el método activate haces:
Código Delphi [-]
procedure TDBexplorer.Activate(Sender: TObject);
begin
  if Assigned(Explorador) then
  begin
    if Assigned(FOldOnActivate) 
      FOldOnActivate(Sender);
    // El código que debe ejecutar tu componente...
  end
end;

Lo que se hace aquí, es guardar el antigüo manejador de evento, y luego, si este estaba asignado, hacer la llamada...


Espero que esto te ayude a solucionar tu problema...


Saludos...

Última edición por maeyanes fecha: 30-09-2005 a las 22:04:41.
Responder Con Cita
  #6  
Antiguo 01-10-2005
lento manu lento manu is offline
Miembro
 
Registrado: oct 2004
Posts: 29
Poder: 0
lento manu Va por buen camino
Gracias Mareyanes

Gracias Marcos. Si me ha servido, por supuesto. Sobre todo a que el código esté claro, no contenga la redundancia que contenía al repetir las llamadas internas de un evento ya escrito. No sospechaba ni en lo más remoto que
Código Delphi [-]
FOldOnActivate := Explorador.OnActivate;
pudiera funcionar, todavía no comprendo bien por qué funciona, pero ya me entrará en la cabezota.
El comportamiento, después de los cambios que me sugieres, es de hecho, el mismo. Quiero decir, que en el Inspector de Objetos, me aparece el evento OnActivate, que por lo menos, ejecuta el evento asociado en el form que se creará, pero si escribo código en este evento, que necesito para realizar un locate, este no se ejecuta, aunque lo escriba con inherited. Si tienes alguna idea... ...Acabo de probar esto y EUREKA: funciona. Evidentemente por eso me has recomendado utilizar una nueva variable FOldOnActivate, para mantener la heredada y la propia. Dejando el procedimiento así, se me ejecutan ambas:
Código Delphi [-]
procedure TDBexplorer.Activate(Sender: TObject);
begin
  inherited;
    if Assigned(Explorador) then
    begin
       if Assigned(FOldOnActivate) then
          FOLdOnActivate(Sender);
       if Assigned(FOnActivate) then
          FOnActivate(Sender);
    end;
end;
Muchísimas gracias por el empujoncito: me he estampado con lo que iba buscando.
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro


La franja horaria es GMT +2. Ahora son las 22:25:00.


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
Copyright 1996-2007 Club Delphi