Вы находитесь на странице: 1из 4

Abrir y cerrar formularios

Método ShowDialog (para mostrar un formulario de manera modal, el código espera una respuesta del
formulario modal)
Método Show (para abrir los formularios no modales, el código continua ejecutándose).

Mientras que los formularios no modales mostrados mediante el método Show se destruyen cuando son
cerrados, no sucede lo mismo con los formularios modales llamados con el método ShowDialog, los cuales
se ocultarán haciéndonos creer que se han cerrado y destruido.

Escenario 1. Utilizar una variable objeto a nivel de clase para mostrar un formulario de manera no modal.

Private m_frm As New Form2


m_frm.Show()
idéntico resultado:
m_frm.Visible = True
‘ Se mostrará el segundo formulario de manera no modal, lo que significa que el código seguirá su
ejecución en las líneas siguientes a la llamada del método Show.

El orden en el que se desencadenan los eventos al cerrar el formulario no modal, o al llamar al método
Close del formulario, que viene a ser lo mismo, sería el siguiente:

1. FormClosing. Antes de que se cierre el formulario.


2. FormClosed. Después de haberse cerrado el formulario.
3. Disposed. Cuando el formulario se ha eliminado mediante una llamada a su método Dispose.

Al cerrarse el formulario no modal, el valor de la propiedad IsHandleCreated pasa a ser False


cuando se ejecuta el evento Disposed del formulario, o cuando explícitamente se llame al método
Dispose del propio formulario, por lo que éste ya no tendrá un identificador asociado.

Para no obtener la excepción ObjectDisposedExcepction cuando desee nuevamente mostrar el


formulario, tendrá que verificar el valor de la propiedad IsHandleCreated, y si su valor es False,
necesitará crear una nueva instancia del formulario:

If (m_frm Is Nothing) OrElse (Not m_frm.IsHandleCreated) Then


m_frm = New Form2()
End If

Otra forma:

Private frmSegundo As Form2


Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
If (frmSegundo Is Nothing OrElse frmSegundo.IsDisposed) Then
frmSegundo = New Form2()
frmSegundo.Show()
Else
frmSegundo.Activate()
End If
Otra forma:

Private frmSegundo As Form2


Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
If (frmSegundo Is Nothing) Then
frmSegundo = New Form2()
AddHandler frmSegundo.FormClosing, AddressOf frmSegundoClosing
End If
If (Not frmSegundo.Visible) Then
frmSegundo.Show()
End If
End Sub
Private Sub frmSegundoClosing(sender As Object, e As FormClosingEventArgs)
RemoveHandler frmSegundo.FormClosing, AddressOf frmSegundoClosing
frmSegundo = Nothing
End Sub

Escenario 2. Utilizar una variable objeto a nivel de clase para mostrar un formulario de manera modal.

Private m_frm As New Form2


m_frm.ShowDialog()

Los únicos eventos que se desencadena cuando se cierra un formulario modal, o simplemente se
llame a su método Close, son los siguientes:
1. FormClosing. Antes de que se cierre el formulario.
2. FormClosed. Después de haberse cerrado el formulario.

Observe que no se ejecuta el evento Disposed, y eso se debe a que no se ha llamado expresamente
a su método Dispose, porque el formulario se encuentra oculto, de ahí que podamos leer los valores
de las propiedades de Form2 desde el formulario llamador, aún después de cerrar supuestamente
el formulario modal. En este caso, al no encontrarse completamente cerrado el formulario, se
necesita hacer una llamada al método Dispose para destruir el formulario una vez que no tengamos
intención de utilizarlo más:

' Comprobamos si existe un identificador asociado.

If (m_frm Is Nothing) OrElse (Not m_frm.IsHandleCreated) Then


m_frm = New Form2()
End If

m_frm.ShowDialog()
' Este código no continua hasta que se cierra el formulario modal.
' Hacemos las operaciones con el formulario m_frm
' Destruimos el formulario.
m_frm.Dispose()

Tras llamar al método Dispose es cuando se desencadenará el evento Disposed, con lo cual se
desencadenarían los mismos tres eventos de cierre que se desencadenan cuando cerramos un formulario no
modal: FormClosing, FormClosed y Disposed.
Escenario 3. Controlar desde un mismo formulario el cierre de otros formularios existentes en nuestro
proyecto.

Llamar a distintos formularios modales y no modales desde un mismo formulario, sobre todo si estamos
trabajando con formularios MDI secundarios.

1. En el formulario de inicio, efectúe la siguiente declaración a nivel del módulo de clase del formulario, para
que pueda acceder a la variable objeto declarada desde otros procedimientos existentes en el formulario:

Private m_frm As Form = Nothing

2. Cree los siguientes procedimientos en el formulario de inicio, los cuales se ejecutarán posteriormente en
sustitución de los eventos Dispose, FormClosed y FormClosing. Por supuesto, deberá de escribir en ellos el
código que desee ejecutar en cada caso:

Private Sub FrmDisposed(ByVal sender As Object, ByVal e As EventArgs)

' Obtenemos la referencia al objeto o formulario que ha provocado el evento.


Dim frm As Form = DirectCast(sender, Form)

' Se produce cuando el componente se elimina mediante una llamada al método Dispose.
MessageBox.Show("Evento Disposed")

End Sub

Private Sub FrmClosed(ByVal sender As Object, ByVal e As FormClosedEventArgs)


' Obtenemos la referencia al objeto o formulario que ha provocado el evento.
Dim frm As Form = DirectCast(sender, Form)

' Se produce después de haberse cerrado el formulario.


MessageBox.Show("Evento FormClosed")

' Si no se trata de un formulario MdiChild, llamamos a su método Dispose.


If ((frm IsNot Nothing) AndAlso (Not frm.IsMdiChild)) Then frm.Dispose()

' Eliminamos la referencia al objeto


' frm = Nothing
End Sub

Private Sub FrmClosing(ByVal sender As Object, ByVal e As FormClosingEventArgs)

' Obtenemos la referencia al objeto o formulario que ha provocado el evento.


Dim frm As Form = DirectCast(sender, Form)

' Se produce antes de cerrar el formulario.


MessageBox.Show("Evento FormClosing")

End Sub
Observe que en el procedimiento FormClosed se ejecutará la llamada al método Dispose de la instancia
actual del formulario, siempre y cuando no se trate de un formulario MDI secundario, ya que éstos
necesariamente se mostrarán de manera modal, de esta manera, ya no es necesario llamar a dicho método
tras cerrar (u ocultar) el formulario modal.

En cuanto a establecer o no el valor Nothing en el evento FormClosed, dicho valor no tendrá efecto alguno
sobre la instancia del objeto referenciada, por lo que una vez ejecutado el evento, se puede seguir utilizando
los métodos y propiedades de la instancia actual del objeto.

3. Cuando desee llamar de manera modal a un formulario concreto, ejecute lo siguiente:

' Creamos la instancia del formulario.


m_frm = New Form2()

' Añadimos los correspondientes procedimientos de evento que deseamos controlar.


AddHandler m_frm.Disposed, AddressOf FrmDisposed
AddHandler m_frm.FormClosed, AddressOf FrmClosed
AddHandler m_frm.FormClosing, AddressOf FrmClosing

' Lo mostramos de manera modal.


m_frm.ShowDialog(Me)

' Si lo creemos oportuno, leemos ciertas propiedades Public o Friend existentes en el formulario llamado.
If (m_frm.DialogResult = Windows.Forms.DialogResult.OK) Then
MessageBox.Show(m_frm.Text, "Disposed=" & m_frm.IsDisposed.ToString)
End If

' Por último, destruimos el formulario modal.


m_frm.Dispose()

Si prefiere llamar a un formulario MDI secundario, efectúe la llamada de la siguiente manera:

' Mostramos de manera no modal un formulario MDI secundario


With m_frm
.MdiParent = Me
.Show()
End With

Como habrá tenido oportunidad de comprobarlo, hemos utilizado una variable objeto de la clase Form, para
crear instancias específicas de un formulario concreto existente en nuestro proyecto. Asimismo, mediante la
instrucción AddHandler hemos asociado tres eventos de la clase Form a sus controladores de evento
correspondientes, de esta manera, desde un único formulario podemos controlar el cierre de los formularios
llamados, con lo cual estaremos a la misma vez reutilizando nuestro código fuente.

http://www.mvp-access.es/softjaen/vbnet/framework/form/sjvbnetfrm02.htm