Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Eventos (https://www.clubdelphi.com/foros/showthread.php?t=64217)

Nove bb net 22-03-2009 23:21:13

Eventos
 
Estoy intentando mediante el uso de application.mainform, en la creacion de un componente, y cuando este en ejecucion, que no en diseño, almacenar, caso que este definido en el form, un evento, para poder ejecutarlo despues del que se debe ejecutar.

Por ejemplo,

Código Delphi [-]
tpanelcentrable=class(tcustompanel)
  ...

  FonResize_del_form: TnotifyEvent;
  FOnResize_delCompo:TnotifyEvent;
  ...

  Property OnResize: TnotifyEvent read FOnResize_del_Compo Write
    FOnResize_del_Compo;

  ....

constructor TPanelCentrable.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  if not (csDesigning in ComponentState) then
  begin
    if assigned(tform(application.MainForm).OncanResize) then
      fonresize_del_form:=tform(application.MainForm).OncanResize;
    tform(application.MainForm).OnCanResize:=formresize;
  end;
end;

Procedure TpanelCentrable.formresize(sender:tObject);
begin
  Centrar(self,self.parent);
  if assigned(FOnResize_del_form) then
    FOnResize_del_form(sender);
  if assigned(FOnresize_del_compo) then
    FOnResize_del_compo(sender);
end;

...

Pero, cuando ejecuto, antes de hacer nada, me salta un error del tipo:

Project programa1.exe raised exception class EAccesViolation with message 'Acces
violation at adrress.....

y en el IDE se queda en;

if assigned(tform(application.MainForm).OncanResize) then


Por favor, ¿alguien me puede ayudar con este tema?

Gracias.
Nove:confused:

Lepe 23-03-2009 14:41:51

Pon el código que usas en tu mainForm

Edito: Vaya, ya veo el problema.

No deberías sustituir los eventos del form Padre. Creo lo estás haciendo al revés, es decir, sería el Form donde sitúas ese panel, el encargado de centrar dicho panel.

¿Qué pasa si pones ese panel en un TFrame, PageControl, dentro de otro panel, etc? Pues obvio, access violation al canto por ese moldeo de tipos que usas.


Quizás tu problema lo puedas solventar sin programar nada usando la propiedad Anchor del Form (si tu delphi lo soporta)

Saludos

Nove bb net 23-03-2009 22:00:28

Re: Eventos
 
El que intente interceptar el onresize del form, es porque es un mensaje seguro si se redimensiona la aplicacion.

Lo que quiero es que mi panel se centre, y luego, el usuario ha podido definir sus acciones en el form..

De hecho, lo que yo hago al centra es usar:
Centrar(self,self.parent);

vamos la tipica de
self.top:=(self.parent.clientheight-self.height) div 2;
self.left:= (self.parente......
Por eso, no debe dar problemas de uso al ser en aplicaciones.

Saludos.
Gracias por tu propuesta, mirare lo de Anchor, pero creo que seria mejor trabajar con el metodo que pretendo, ya que permitiria que el usuario haga lo que quiera, pero respetando siempre lo que el crador del componente ha pensado que era necesario para su correcto funcionamiento.

Nove

Lepe 24-03-2009 09:56:13

Vale, te doy otra razón para no usar ese método:

if assigned(tform(application.MainForm).OncanResize) then

eso se cumple si el programador final, en el form principal de la aplicación, ha escrito algo de código en el evento OncanResize. Por tanto no es seguro que se cumpla esa condición.

Se supone que haciendo doble clic en inspector de objetos, en el evento Oncanresize , ya cumpliría la condición, pero como sabes delphi elimina los eventos vacíos. En el caso de que añadas un comentario a ese evento, quizás el optimizador de código de delphi quite el evento porque vea que tiene un contenido supérfluo, no sé, no estoy seguro al 100 %

Otro detalle: ¿por qué usas application.MainForm? ¿el usuario de tu componente no puede ponerlo en un Form secundario?


Saludos

Nove bb net 24-03-2009 16:56:07

Gracias a todos.
 
Realmente estaba empeñado, en que el ordn de construccion era distinto, pero.

Realmente solo pense en el formulario inicial, y no en otros secundarios, pero

Creo que esto funciona en todos los casos, por lo menos en los que he probado.

Código Delphi [-]
  Tcustompanelcentrado=class(tcustompanel)
  private
    foncanresizedelform:controls.tcanresizeevent;
    finiciado:boolean;
    procedure centrar;
  protected
  public
    constructor create(aowner:tcomponent); override;
    procedure paint; override;
    procedure canresizecompo(Sender: TObject; var NewWidth,
                             NewHeight: Integer; var Resize: Boolean);
  end;

  tpanelcentrado=class(tcustompanelcentrado);

implementation

constructor tcustompanelcentrado.create(aowner:tcomponent);
begin
  inherited create(aowner);
  finiciado:=false;
end;

procedure tcustompanelcentrado.paint;
var misterx:tcontrol;
begin
  if not finiciado then
    begin
      if not (csDesigning in ComponentState) then
        begin
          misterx:=self.Parent;
          while not(misterx is tform) do
            misterx:=misterx.Parent;

          if assigned(tform(misterx).OncanResize) then
            begin
              foncanresizedelform:=tform(misterx).oncanresize;
            end;
          tform(misterx).OnCanResize:=canresizecompo;

          centrar;

          finiciado:=true;
        end;
    end;
    inherited;
end;

procedure tcustompanelcentrado.centrar;
begin
  top:=(self.Parent.ClientHeight-height) div 2;
  left:=(self.Parent.ClientWidth-width) div 2;
end;

procedure tcustompanelcentrado.CanResizecompo(Sender: TObject; var NewWidth,
          NewHeight: Integer; var Resize: Boolean);
begin
  if assigned(foncanresizedelform) then
    foncanresizedelform(sender,newwidth,newheight,resize);
  centrar;
end;

perdon por no tenerlo puesto en una undiad independiente, es que hay otros compos.

Saludos.
Nove:):o;):):o

Lepe 25-03-2009 17:26:23

Mejor :).


Como crítica constructiva, podrías añadir una propiedad AutoCenter:Boolean que fuese True por defecto ¿para qué? para que tu usuario se olvide de los TPanel y pueda usar el tuyo aun cuando no requiera la capacidad de autocentrarse.

Cuando estás creando una interfaz, es muy normal andar probando distintas alternativas y si tiene que cambiar el Tpanel por un TPanelcentrado es engorroso, si ya usa un TPanelcentrado, sólo tiene que poner AutoCenter a True o false para ver cómo queda la nueva interfaz ;).

El cambio es simple:
Código Delphi [-]
Tcustompanelcentrado=class(tcustompanel)
private
  FAutoCenter:Boolean;
published // mostrada en el Inspector de objetos.
  propery AutoCenter:Boolean read FAutoCenter write FAutoCenter default True;
end;

constructor tcustompanelcentrado.create(aowner:tcomponent);
begin
  inherited create(aowner);
  finiciado:=false;
  FAutoCenter:= True;
end;

procedure tcustompanelcentrado.CanResizecompo(Sender: TObject; var NewWidth,
          NewHeight: Integer; var Resize: Boolean);
begin
  if assigned(foncanresizedelform) then
    foncanresizedelform(sender,newwidth,newheight,resize);
  if FAutoCenter then
    centrar;
end;

Saludos

Nove bb net 26-03-2009 00:21:15

Eventos
 
Nuevamente, se demuestra que el compartir una duda facilita la solucion, y enriquece las ideas al que la plantea.

Reconozco que el crear una propiedad Autocentrar, es muy buena idea, y cualquier cosa que el usuario, si le interesa el compo, todo el esqueleto esta en un mensaje anterior, pueda añadirle sea bienvenido.

Igualmente he de agradecer el hecho de que se haga ver un punto que no tenia pensado, si el usuario cambia por codigo, en tiempo de ejecucion el evento xxform.oncanresize por otro, o por nil, nos encontramos que todo el mecaniso de centrado falla, ya que es ese evento que se ha modificado el que lanzaba todo el mecanismo de centrado y queda sustituido integramente por lo que el usuario haga en dicho evento.

Gracias, pero esta vez no es tan facil, bueno, tal vez si, si comprobaramos que la direccion de la rutina del evento es la misma que esta almacenada.
Si no es asi, se debe cambiar para recoger la nueva, modificando la almacenada del form en nuestro compo por la nueva y volviendo a regenerar el manejador del evento del compo.

Veremos..

Saludos.
Nove bb net:):rolleyes::rolleyes::rolleyes::rolleyes::rolleyes::rolleyes::rolleyes::rolleyes::rolleyes:

Nove bb net 26-03-2009 15:37:12

Eventos
 
Ahora ya si que necesito toda la ayuda.

hasta ahora el panelcentrable, estaba tomando forma, y de hecho, ha tomado bastante color, pero, siempre existe el pero, ahora, cuando el usuario, una vez iniciada la aplciacion, cambia el evento OnCanResize del form en el que se ha colocado el panelcentrable, y hasta tanto en cuando que el panel no necesita pintarse de nuevo, se comporta erraticamente, vamos que no se centra.

Alguien tiene una idea de como evitar ese comportamiento temporaldel panel, hasta que se vuelve a Paint.

Este es el codigo de todo lo hecho.

Lo he separado en una unidad totalmente utilizable, salvo por el detalle antes mencionado.

Gracias.
Nove :confused::confused::confused::confused:

Código Delphi [-]
unit Customcentrablepanel1;

interface

uses
  SysUtils, Classes, Controls, ExtCtrls, buttons, comctrls, stdctrls,
  dialogs, forms, types;

type
  TCustomcentrablepanel1 = class(TCustomPanel)
  private
    { Private declarations }
    misterx:tcontrol;
    argo:pointer;
    finiciado:boolean;
    foncanresizedelform:controls.TcanresizeEvent;
    //Gracias a Lepe
    TAutoCenter:boolean;
    procedure setAutocenter(valor:boolean);

    procedure setalign(valor:talign);
    function getalign:talign;

    procedure centrar;
    procedure canresizecompo(Sender: TObject; var NewWidth, NewHeight: Integer; var Resize: Boolean);

  protected
    { Protected declarations }
  public
    { Public declarations }
    constructor create(aowner:tcomponent); override;
    procedure paint; override;
    property AutoCenter:Boolean read TAutoCenter write setAutoCenter default True;
    property Align:Talign read getalign write setalign default alnone;
    { Published declarations }
    published
  end;

  Tcentrablepanel=class(tcustomcentrablepanel1)
  public
    property DockManager;
  published
    property Align;
    property Alignment;
    property Anchors;
    property AutoCenter;
    property AutoSize;
    property BevelInner;
    property BevelOuter;
    property BevelWidth;
    property BiDiMode;
    property BorderWidth;
    property BorderStyle;
    property Caption;
    property Color;
    property Constraints;
    property Ctl3D;
    property UseDockManager default True;
    property DockSite;
    property DragCursor;
    property DragKind;
    property DragMode;
    property Enabled;
    property FullRepaint;
    property Font;
    property Locked;
    property ParentBiDiMode;
    property ParentBackground;
    property ParentColor;
    property ParentCtl3D;
    property ParentFont;
    property ParentShowHint;
    property PopupMenu;
    property ShowHint;
    property TabOrder;
    property TabStop;
    property Visible;
    property OnCanResize;
    property OnClick;
    property OnConstrainedResize;
    property OnContextPopup;
    property OnDockDrop;
    property OnDockOver;
    property OnDblClick;
    property OnDragDrop;
    property OnDragOver;
    property OnEndDock;
    property OnEndDrag;
    property OnEnter;
    property OnExit;
    property OnGetSiteInfo;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
    property OnResize;
    property OnStartDock;
    property OnStartDrag;
    property OnUnDock;
  end;

procedure Register;

implementation

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

constructor TCustomcentrablepanel1.create(aowner:tcomponent);
begin
  inherited create(aowner);
  finiciado:=false;
  //Gracias a Lepe
  tautocenter:=true;
end;

procedure TCustomcentrablepanel1.centrar;
begin
  top:=(self.parent.clientheight-height) div 2;
  left:=(self.Parent.ClientWidth-width) div 2;
end;

procedure TCustomcentrablepanel1.canresizecompo(Sender: TObject; var NewWidth, NewHeight: Integer; var Resize: Boolean);
begin
  if assigned(foncanresizedelform) then
    foncanresizedelform(sender,newwidth,newheight,resize);
  if tautocenter then
    centrar;
end;


procedure tcustomcentrablepanel1.paint;
var ac:^tmethod;
    af:^tmethod;
begin
  if not (csdesigning in componentstate) then
    if not finiciado then
      begin
          begin
            misterx:=self.Parent;
            while not(misterx is tform) do
              misterx:=misterx.Parent;
            if assigned(tform(misterx).OnCanResize) then
               foncanresizedelform:=tform(misterx).OnCanResize;
            tform(misterx).OnCanResize:=canresizecompo;
            af:=@@tform(misterx).oncanresize;
            argo:=af.code;
          end;
        finiciado:=true;
        centrar;
      end
      else
      begin
        ac:=@@tform(misterx).oncanresize;
        if ac.Code<>argo then
          begin
            if assigned(tform(misterx).OnCanResize) then
               foncanresizedelform:=tform(misterx).OnCanResize
               else
               foncanresizedelform:=nil;
            tform(misterx).OnCanResize:=canresizecompo;
            af:=@@tform(misterx).oncanresize;
            argo:=af.code;
            centrar;
          end;
    end;
  inherited;
end;

procedure tcustomcentrablepanel1.setAutocenter(valor:boolean);
begin
  if tautocenter<>valor then
    begin
      tautocenter:=valor;
      if tautocenter=true then
        align:=alnone;
      invalidate;
    end;
end;

function tcustomcentrablepanel1.getalign:talign;
begin
  result:=inherited align;
end;

procedure tcustomcentrablepanel1.setalign(valor:talign);
begin
  if valor<>inherited align then
    begin
      if tautocenter then
        inherited align:=alnone
        else
        inherited align:=valor;
    end;
end;

end.


La franja horaria es GMT +2. Ahora son las 22:51:12.

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