FTP | CCD | Buscar | Trucos | Trabajo | Foros |
#1
|
|||
|
|||
Suma de eventos
Buenas, en mi caso es con eventos de qreports, pero yo supongo que puede usarse en los eventos de cualquier componente, por esto lo he puesto en este foro.
La pregunta es: Yo me repaso una serie de componentes del formulario, y segun unas caracteristicas, les pongo en su evento, otro evento,que es el mi propio evento. Pues bien,el problema reside, cuando el evento tenia ya codigo asignado. ¿como puedo yo en ese caso hacer que primero, ejecute el código que tenia ya asignado el evento, y luego el evento que yo le he puesto? En micaso es con el before print del quick report. Saludos Muchas Gracias |
#2
|
||||
|
||||
La forma típica es guardar ese evento en una variable, y llamarla antes o despues del evento:
Código:
type TForm1 = class(TForm) Button1: TButton; procedure FormCreate(Sender: TObject); procedure Button1Click(Sender: TObject); private FOldOnClick: TNotifyEvent; procedure MiEvento(Sender: TObject); public end; implementation ... procedure TForm1.FormCreate(Sender: TObject); begin FOldOnClick := Button1.OnClick; Button1.OnClick := MiEvento; end; procedure TForm1.Button1Click(Sender: TObject); begin ShowMessage('Hola Mundo!'); end; procedure TForm1.MiEvento(Sender: TObject); begin if Assigned(FOldOnClick) Then FOldOnClick(Self); ShowMessage('¿Ok?'); end; procedure TForm1.FormDestroy(Sender: TObject); begin Button1.OnClick := FOldOnClick; end; Saludos!
__________________
delphi.com.ar Dedique el tiempo suficiente para formular su pregunta si pretende que alguien dedique su tiempo en contestarla. |
#3
|
|||
|
|||
Muchas gracias, ahora luego probare, aunque por el codigo que veo, esta bastante claro, i creo que no tendre ningun problema
Gracias de nuevo saludos |
#4
|
|||
|
|||
perdona una cosa, me da el error de incompatible types de tobject and tqrcustomband.
Claro el tnotify event es para un tobject, y ¿ tqrcustomband no deriva de tobject? el error es en esta linea ant := Tqrcustomband(Components[i]).BeforePrint; ant es tnotifyevent; La finalidad, es que de esta manera recorriendome todos los componentes del form, cuando yo veo que son tqrcustomband, guardarme su beforeprint en un tnotifyevent. supongo que tendre que hacer una array de tnotifyevent.¿Se puede no? ¿hacer un cast de Tqrcustomband a tobject, sera la solucion? Gracias por la ayuda |
#5
|
|||
|
|||
ok yo mismo me respondo que lo encontre
TQRBandBeforePrintEvent Saludos Y muchas gracias por todo |
#6
|
||||
|
||||
Cita:
Cita:
Cita:
Código:
var FOldEvento: TQRBandBeforePrintEvent; begin FOldEvento := Tqrcustomband(Components[i]).BeforePrint; ... end;
__________________
delphi.com.ar Dedique el tiempo suficiente para formular su pregunta si pretende que alguien dedique su tiempo en contestarla. |
#7
|
||||
|
||||
Cita:
Saludos!
__________________
delphi.com.ar Dedique el tiempo suficiente para formular su pregunta si pretende que alguien dedique su tiempo en contestarla. |
#8
|
||||
|
||||
¡Buen día a todos!
Descendents: ¿Por qué no colocas el código específico directamente en el manejador de evento? ¿Será que son manejadores de eventos compartidos y ese código específico no es para todos los objetos, o bien, ese código específico se requiere también en otras rutinas? Mencionas algo de "según unas características". ¿Podrías ser un poco más específico? Me gustaría entender con mayor precisión el problema, para ayudar en la medida de lo posible. Muchas gracias. Al González . |
#9
|
|||
|
|||
el error esta aqui
if Assigned(ant) Then ant(sender,true); ¿Alguien sabe cual es este error? [Error] Unit1.pas(72): Types of actual and formal var parameters must be identical he buscado en la ayuda, pero me habla de que byte no es lo mismo que 0..255. Pero yo necesito llamar al TQRBandBeforePrintEvent al tnotifyevent con el self ya estaba, pero aqui me pide un tqrcustomband y un booleano de printband. es decir esto procedure TForm1.PageHeaderBand1BeforePrint(Sender: TQRCustomBand; var PrintBand: Boolean); ¿Porque puede darme este error? Soy un pesado lo se, pero esto no se como afrontarlo Gracias |
#10
|
||||
|
||||
La respuesta está en tu pregunta, fíjate este pequeño detalle:
Código:
procedure TForm1.PageHeaderBand1BeforePrint(Sender: TQRCustomBand; var PrintBand: Boolean);
__________________
delphi.com.ar Dedique el tiempo suficiente para formular su pregunta si pretende que alguien dedique su tiempo en contestarla. |
#11
|
|||
|
|||
Gracias delphi.com.ar, pero mi desconocimiento me precede, y he visto ya bastantes veces procedimientos, con var y parametros, pero como nunca lo he necesitado, no se como se atacan ni para que sirven.
Si fueras tan amable, mataria varios pajaros de un tiro. Para que sirve,y por que el error, y en que otras ocasiones puede servirme de ayuda he buscado sobre el tema, pero no se como buscar sobre esto exactamente. Yo todos los procedimientos y funciones, siempre les pongo unos parametros, y se los paso, nunca he necesitado parsar una variable como paramentro, principalmente porque no tengo ni idea para que sirve Gracias y perdona la incultura |
#12
|
||||
|
||||
Hola, pongo esta respuesta aquí, porque creo que viene al caso, aunque en realidad no le solucionará la vida a nadie ya que más bien es anecdótica
ültimamente estoy aprendiendo algo de C# y lo cierto es que tiene algunas características muy interesantes y, entre ellas está su implementación de eventos que es lo qua aquí se comenta. El caso es que en C# no puedes asignar un valor a un evento, sino que debes añadir o quitar valores, de manera que, al lanzarse dicho evento se ejecutaran todos los provedimientos "añadidos". Esto és muy, pero que muy potente, ya que en el ejemplo que comentamos, sería algo tan simple como lo siguiente Código:
/*en el create del form1, por ejemplo*/ form2.button1.onClick += metodo1; form2.button1.onClick += metodo2; form2.button2.onClick += metodo1; /*y en el destroy*/ form2.button1.onClick --; form2.button1.onClick --; form2.button2.onClick --; No me digáis que no es chulo!!!!!! Sólo he puesto esto como curiosidad espero no haberme excedido.
__________________
E pur si muove |
#13
|
||||
|
||||
Te recomiendo buscar en la ayuda una página titulada "Value and variable parameters"... en simples palabras, existen dos formas de pasar valores en parámetros de procedimientos, por valor y por referencia. Por valor, el parámetro no deja de ser una variable propia del procedimiento que contendrá el valor que le has asignado al parámetro. Por referencia (var), el parámetro apunta a la misma variable que se ha utilizado en el parámetro, al llamar el procedimiento, por lo tanto requiere que sea una variable y no una constante. Al modificar el valor de la función dentro del procedimiento, se modificará el valor de la variable usada al llamar al procedimiento.
La solución a tu problema, es algo como: Código:
var bPrintBand: Boolean; begin bPrintBand := True; if Assigned(Ant) Then Ant(Sender, PrintBand);
__________________
delphi.com.ar Dedique el tiempo suficiente para formular su pregunta si pretende que alguien dedique su tiempo en contestarla. |
#14
|
|||
|
|||
ok ya entendi, o eso creo almenos.
Pide una referencia a una variable, no un valor. Ok gracias. Aunque si fueran tan amables de decirme si voy bien encaminado y su utilidad. Gracias |
#15
|
|||
|
|||
Mira justo me has respuesto, pues estaba bien encaminado, gracias, buscare más información de todos modos
Muchas gracias,Tema resuelto. Saludos |
#16
|
||||
|
||||
¡Buen día a todos!
Interesante aportación Marto. Por supuesto que se ve muy práctico. Me pregunto cómo será la implementación interna de Propiedad evento += Manejador de evento, es decir el encadenamiento de manejadores, y si este encadenamiento puede ser establecido tanto de la forma manejador anterior + manejador nuevo, como de la forma manejador nuevo + manejador anterior, es decir, con la libertad establecer su ejecución en cualquier orden. Imagino que quizás C# guarda una lista de todos los manejadores asignados al mismo evento de un objeto, o bien, la estructura de rutinas .NET presenta de forma nativa esta característica. Sería interesante averiguar si Delphi 8 también permite este tipo de encadenamientos de manejadores de eventos mediante asignaciones. Lo más parecido que he visto a encadenaciones automáticas de manejadores de eventos, es cuando se define un manejador de evento en una plantilla y en la clase descendiente se vuelve a definir. El segundo llamando al primero con la palabra reservada Inherited (aun sin tratarse de un método virtual). Sin embargo esta aproximación dista mucho de la útil metodología de C# expuesta por Marto. Por otra parte, le pido a Descendents que por favor atienda mi mensaje anterior, para entender mejor los pormenores del caso y tratar de aportar una solución práctica. Seguimos en contacto. Al González. |
#17
|
||||
|
||||
Digamos que en Delphi esto no sería imposible, si quisiéramos escribir un poco de código, podríamos crear algo como una Colección de Eventos, y a la hora de definir un evento, lo podemos definir de este tipo. Internamente lo que tendría que hacer nuestro objeto, es recorrer esta colección y llamar a todos los eventos de esta.
Digamos... por el uso que le daríamos a esta, creo que como siempre la ecuación costo/beneficio sería difícil de evaluar. Saludos!
__________________
delphi.com.ar Dedique el tiempo suficiente para formular su pregunta si pretende que alguien dedique su tiempo en contestarla. |
#18
|
||||
|
||||
Cita:
Un saludo.
__________________
Guía de Estilo de los Foros Cita:
|
#19
|
|||
|
|||
Al gonzalez, perdona, no habia visto tu mensaje anterior, lo he visto a partir de que me dices que te conteste, lo mire y lo vi, perdón.
El tema ya lo tengo solventado, como me guio delphi.com.ar era la manera correcta por donde ir. quiero asignarle un before print mio, a cada banda del report,pero si ya tenia unos calculos en el before print, estos se pierden, pero ahora esto ya no pasa. No puedo poner en cada evento el codigo, porque no me sirve de nada, por que entonces tengo que en todos los reports tener que en cada banda ponerle mi código, y yo quiero que esto se haga automatico. ahora llamo al procedimiento, le paso como paramentro el report, y el solo, me asigna lo que quiero hacer a todas las bandas, indistintamente de las bandas que haya. La caracteristica principal es, que quiero hacer lo mismo en todas las bandas, indiferentemente de si es un detailband o un pageheader o lo que sea, por eso quiero hacerlo de esta manera Saludos |
#20
|
||||
|
||||
¡Hola de nuevo!
Gracias por la aclaración Descendents. Comprendiendo la naturaleza de este caso, debo decir que lo mejor sería crear una nueva clase de objeto banda para Quick Report. Donde el evento BeforePrint esté redefinido. Ejemplo: Código:
Interface ... Type TBandQuickReport = Class (TQRBand) Private FBeforePrint :TQRBandBeforePrintEvent; { Manejador de Evento Before Print interno } Procedure ManeEvenBeforePrint ( Remitente :TQRCustomBand; Var Imprimir :Boolean); Public Constructor Create (AOwner :TComponent); Override; Published { Evento Before Print redefinido (manejador de evento externo) } Property BeforePrint :TQRBandBeforePrintEvent Read FBeforePrint Write FBeforePrint; End; ... Implementation ... { TBandQuickReport } Constructor TBandQuickReport.Create (AOwner :TComponent); Begin Inherited Create (AOwner); Inherited BeforePrint := ManeEvenBeforePrint; End; Procedure TBandQuickReport.ManeEvenBeforePrint ( Remitente :TQRCustomBand; Var Imprimir :Boolean); Begin { Aquí puede ir código común para todas las bandas } { Llamar al manejador de evento BeforePrint externo } If Assigned (BeforePrint) Then BeforePrint (Self, Imprimir); { Aquí puede ir código común para todas las bandas } End; Bajo las circustancias que planteas, creo que definitivamente esta es la solución más adecuada. Esto se acostumbra en programación orientada a objetos cuando se tiene una clase y se crea una segunda clase derivada de la primera para agregarle características extras. Espero esto sea de utilidad. Mantenernos informados. Al González . |
Herramientas | Buscar en Tema |
Desplegado | |
|
|
|