![]() |
![]() |
| Paypal | FTP | CCD | Buscar | Trucos | Trabajo | Foros |
|
|||||||
| Registrarse | FAQ | Miembros | Calendario | Guía de estilo | Buscar | Temas de Hoy | Marcar Foros Como Leídos |
![]() |
|
|
Herramientas | Buscar en Tema | Desplegado |
|
|
|
#1
|
||||
|
||||
|
Mira lo que pude observar es qe tienes una pequeña confusion, te explico cuando haces with ActiceMdiChild as TVentana_Hija estas haciendo un type cast de la clase TVentanaHija, pero cuando haces Ventana_Hija.Caption te da el error debido a que la variable Ventana_Hija no ha sido incializado porq en el procedimiento creas una variable denominada Ventana no ventana_Hija, alli esta tu primer problema...
lo segundo es que para pasar una variable por referencia no se lo indicas al momento de Llamarla solo cuando la defines por ejemplo esta bien hecho cuando lo defines procedure TVentana_Hija.FormCloseQuery(Sender: TObject;var CanClose: Boolean); begin ...... end pero cuando lo llames no le digas Ventana_Hija.FormCloseQuery(nil; var CanClose); dile Ventana_Hija.FormCloseQuery(nil; CanClose); asumiendo que canclose es una variable que tienes definida y no estoy seguro pero creo que tienes que pasarle tambien el form que estas cerrando y no un puntero nil
__________________
...Yo naci en esta ribera del arauca vibr@d0r Soy hermano de la espuma, de la garza, de la rosa y del sol... Viva Venezuela |
|
#2
|
||||
|
||||
|
Veamos el primer problema.
El error está, como he comentado en el mensaje anterior, en la variable que utilizas para referenciar el formulario. Durante la creación que haces del formulario : Código:
procedure TPrincipal.Crear_Ventana(Nombre: String; Modificado: Boolean); var ventana: TVentana_Hija; begin ventana := TVentana_Hija.Create(Self); ventana.Caption := Nombre ; SB_Barra.Panels[1].Text := ventana.Caption; ventana.Show; end; Si aquí mismo hicieras : Código:
Ventana.RE_Editor.Lines.LoadFromFile(OD_Abrir_Fichero.FileName); Ventana.RE_Editor.Modified := False; En cambio, en tu código, una vez creado el formulario, finaliza el procedimiento y desaparece la variable Ventana con que lo has referenciado. Cuando quieres volver a acceder a ella, utilizas la variable Ventana_Hija, cosa que el compilador accepta puesto que es del tipo adecuado, pero como no está inicializada con ningún valor, da un error en ejecución al usarla. Para solucionarlo, una posiblidad es poner todo el código en un solo procedimiento que mantenga una referencia Ventana válida : Código:
procedure TPrincipal.Abrir_FicheroExecute(Sender: TObject); var Ventana: TVentana_Hija; begin if not OD_Abrir_Fichero.Execute then Exit; if not FileExists(OD_Abrir_Fichero.FileName) then Exit; ventana := TVentana_Hija.Create(Self); ventana.Caption := OD_Abrir_Fichero.FileName; SB_Barra.Panels[1].Text := OD_Abrir_Fichero.FileName; Ventana.RE_Editor.Lines.LoadFromFile(OD_Abrir_Fichero.FileName); Ventana.RE_Editor.Modified := False; end; Saludos.
__________________
Marc Guillot (Hi ha 10 tipus de persones, els que saben binari i els que no). |
|
#3
|
||||
|
||||
|
Veamos ahora el segundo problema :
Como han comentado, no hace falta que uses la directiva var al pasar por referencia un parámetro. Esa directiva solo se pone en la definición del parámetro, pero en el momento de llamar a la función, en el parámetro tienes que poner una variable (como podrías hacer perfectamente en una parámetro pasado por valor). Tienes que poner una variable porqué, una vez ejecutado el procedimiento, si se ha modificado el valor, solo tienes que leer el contenido de la variable para conocer el valor modificado. Así pues, la llamada te quedaría : Código:
var PuedeCerrar: boolean; begin PuedeCerrar := True; Ventana.FormCloseQuery(Ventana; PuedeCerrar); end; Como comenté en el primer mensaje, no es nada aconsejable programar de esta forma, accediendo directamente a componentes y llamando a eventos de otros formularios. Esto te complica mucho el mantenimiento del programa, hacer modificaciones, ver donde falla, etc .... Seria mucho mejor que todo lo que quieras hacer sobre un formulario, lo pongas en unos métodos públicos que sean lo único a lo que se accede desde fuera del formulario. Saludos.
__________________
Marc Guillot (Hi ha 10 tipus de persones, els que saben binari i els que no). |
|
#4
|
|||
|
|||
|
Entiendo muy bien lo de las variables locales y globales y como puedo haceder a un formulario desde el mismo codigo.
Guillotmarc escribio: Code: procedure TPrincipal.Abrir_FicheroExecute(Sender: TObject); var Ventana: TVentana_Hija; begin if not OD_Abrir_Fichero.Execute then Exit; if not FileExists(OD_Abrir_Fichero.FileName) then Exit; ventana := TVentana_Hija.Create(Self); ventana.Caption := OD_Abrir_Fichero.FileName; SB_Barra.Panels[1].Text := OD_Abrir_Fichero.FileName; Ventana.RE_Editor.Lines.LoadFromFile(OD_Abrir_Fichero.FileName); Ventana.RE_Editor.Modified := False; end; Pero que pasa cuando quieres haceder a cualquier formulario, ya creado,para poder hacer cosas en el. Porque en el ejemplo anterior lo que hacemos es crear un formulario nuevo y a la vez aprobechamos para actualizarle. Tambien dices que no recomiendas acceder a otros formularios desde otros. Pero es imposible, por ejemplo: En este editor de texto dispongo de una barra de herramientas y un menú, que están ubicados en la ventana padre o principal. El principal componente de este programa lógicamente es un editor de típo TrichEditor y este componente está en la ventana hija. Cuando yo pulso el botón cerrar ventanas que está ubicado en la ventana principal o padre, me estoy refiriendo o deseo referirme a una ventana hija, que pertenece a otro formulario. Mi problema en concreto es en la parte de cerrar ventanas.En el formulario de la ventana hija he utilizado el evento: procedure TVentana_Hija.FormCloseQuery(Sender: TObject;var CanClose: Boolean); Y lo he codificado tal y como me sugieres pero me da error en la ejecución. Pero tambien en la ventana padre, en la barra de herramientas, he incluido un boton para cerrar ventanas y lo que yo pretendia es desde el procedimiento de ese boton(codigo padre) hacer una llamada al procedimiento anteriormente citado de cerrar ventanas, situado en el formulario de la ventana hija. He realizado lo de poner el procedimiento en la sección public y he conseguido ejecutar el programa pero no ejecuta bien el procedimineto ya que no cierra ventanas. Tal vez una solucción sería hacer codigos independientes para cada botón? De todas formas voy a seguir estudiando el tema y ya os contaré. Salu2 |
|
#5
|
||||
|
||||
|
Hola.
He estado una semana fuera, ¿ como tienes el tema ?, ¿ has podido solucionarlo ? Saludos.
__________________
Marc Guillot (Hi ha 10 tipus de persones, els que saben binari i els que no). |
|
#6
|
|||
|
|||
|
Hola Guillotmarc.
Estoy en un punto muerto, digamos que he tirado la toalla. No he sabido, o podido, dar con ello. Con la llamada a otro procedimiento lo que queria hacer es, logicamente, evitar escribir de nuevo parte del codigo. Consegui hacer la llamada sin que me diese error alguno ni al compilar ni en ejecución, pero al pulsar el boton el programa no hacia nada. Cuando me empezo a salir humo por las orejas , decidi olvidarme de la llamada al procedimiento y ejecutar para ese procedimiento unas nuevas sentencias. Pero, de nuevo, la suerte no me acompaño.Resumiendo un poco, yo dispongo de un editor con ventanas MDI. Codifique el evento On CloseQuery de la ventana hija, y funciona bien. En la ventana principal o padre, dispongo de una barra de herramientas y en ella está un boton para cerrar ventanas (activas).Mi idea al principio fue, desde este boton realizar una llamada al procedimiento del formulario hijo, On CloseQuery y así cerrar las ventanas. Pero y Ultimamente, como he dicho antes, he codificado nuevas sentencias para ese boton: var respuesta,i: integer; Ventana_Activa: string; ventana: TVentana_Hija; { for i := 0 to MI_Ventana.Count - 1 do if (MI_Ventana.Items[i].Tag = 0) then if (MI_Ventana.Items[i].Checked = True) then Ventana_Activa := MI_Ventana.Items[i].Caption; } ventana := Application.FindComponent(ActiveMDIChild.Caption) as TVentana_Hija; if assigned (ventana) then ventana.Show else exit; if (ventana.RE_Editor.Modified) then begin Respuesta := Application.MessageBox('¿Desea guardar los cambios? ', ' Guardar',mb_IconWarning + mb_yesNoCancel); Case Respuesta of idYes: begin if (FileExists (ventana.Caption)) then begin ventana.RE_Editor.Lines.SaveToFile(ventana.Caption); Close; end else begin if(SD_Guardar_Fichero.Execute) then begin SD_Guardar_Fichero.Filename := Ventana_Activa; ventana.RE_Editor.Lines.SaveToFile(ventana.Caption); Close; end; end; end; idNo : Close; idCancel: ; end; end else Close; Este es el procedimiento que estoy utilizando. Problemas: creo que no me asigna nada a la variable ventana y como ñe tengo puesto exit , pues se sale del procedimiento. es decir, que cuando pulso el boton no ocurre nada. Tambien intente, como se ve arriba, darle el nombre de la ventana cogiendolo del menu ventana, pero tampoco funciona. Una vez que conseguí entrar en el procedimiento me lo ejecutaba dos veces, por ejemplo`pulsaba el boton y aparecia el mensaje de si quería guardar los cambios, le decia, por ejemplo, que no y volvia a salir de nuevo el memnsaje y si pulsaba de nuevo que no se cerraba la ventana. Otra cosa que me sucede en este y en el otro procedimiento (On CloseQuery) es que he observado que las ventanas nuevas (en blanco) se crean con la propiedad modified en True, a pesar de que al crear estas ventanas le coloco una sentencia, que tambien está en el botón abrir y si funciona, en la que le pongo la propiedad a false. Tambien el el boton on create de la ventana hija le tengo puesto otra sentencia el la que pongo modified a false. Bueno, como puedes ver, estoy bastante entretenido De todas formas te agradezco mucho que te hallas acordado de mi. Muchas gracias. |
|
#7
|
|||
|
|||
|
Perdona no hagas caso a mi anterior mensaje. SI que he conseguido entrar en el procedimiento de esta forma:
var respuesta: integer; begin with (ActiveMDIChild as TVentana_Hija) do begin if (RE_Editor.Modified) then begin Respuesta := Application.MessageBox('¿Desea guardar los cambios? ', ' Guardar',mb_IconWarning + mb_yesNoCancel); Case Respuesta of idYes: begin SD_Guardar_Fichero.Filename := Caption; if (FileExists (SD_Guardar_Fichero.Filename)) then begin RE_Editor.Lines.SaveToFile(SD_Guardar_Fichero.Filename); Close; end else begin if(SD_Guardar_Fichero.Execute) then begin RE_Editor.Lines.SaveToFile(SD_Guardar_Fichero.Filename); Close; end; end; end; idNo : Close; idCancel: ; end; end else Close; end; Pero si es cierto que se me ejecuta dos veces a partir de que hago una modificacion en el documento, es decir si tengo un documento en el que la propiedad modified está en False y pulso el botón cerrar, la v3ntana se cierra bien. Pero en el momento que entra en la sentencia: if (RE_Editor.Modified) then, todas las opciones que tóme se repiten, eso si al final de la segunda vez si que se realiza lo que halla elegido. Lo ultimo que te cuento, lo de que un documento nuevo se inicia con la propiedad modified en true, tambien me sigue ocurriendo. Por ejemplo cuando creo una ventana nueva se pulso el boton cerrar ventana, en vez de cerrarse tal cual, me entra en la sentencia if (RE_Editor.Modified) then y me pregunta si deseo guardar los cambios. Perdona el desliz. Salu2 |
![]() |
| Herramientas | Buscar en Tema |
| Desplegado | |
|
|
|