Menú de navegaciónMenú
Categorías

La mejor forma de Aprender Programación online y en español www.campusmvp.es

?id=37ce75f9-1591-4b27-aae0-6b13c7318d3b

TRUCO: Cómo averiguar si una ventana ha sido cerrada por el usuario

Icono de advertencia ATENCIÓN: este contenido tiene más de 2 años de antigüedad y, debido a su temática, podría contener información desactualizada o inexacta en la actualidad.

Las ventanas de Windows (formularios Windows Forms) se pueden cerrar, bien por parte del usuario, o bien mediante programa con el método Close(). Pero ¿cómo distinguir ambos casos?

En Visual Basic "clásico" era muy fácil hacerlo dentro del evento QueryUnload gracias al parámetro UnloadMode. Sin embargo en .NET no es tan sencillo averiguarlo.

Cómo saber si una ventana ha sido cerrada por el usuario

Aunque no es tan flexible como el evento QueryUnload mencionado, la solución que se expone a continuación soluciona el problema.

Se trata de subclasificar el procedimiento de la ventana y verificar que el mensaje que se está produciendo es WM_SYSCOMMAND con el parámetro SC_CLOSE, así (en C#):

public const int SC_CLOSE = 0xF060;
public const int WM_SYSCOMMAND = 0x0112;

protected override void WndProc(ref System.Windows.Forms.Message m) { 
  if(m.Msg == WM_SYSCOMMAND && (int)m.WParam == SC_CLOSE)
     //La cerró el usuario
     base.WndProc(ref m);
}

Si queremos podemos cancelar el proceso del mensaje para cancelar el cierre de la ventana en caso de que sea el usuario quien lo haya provocado (hay situaciones en las que puede ser muy útil).

Fecha de publicación:
José Manuel Alarcón Fundador de campusMVP, es ingeniero industrial y especialista en consultoría de empresa. Ha escrito diversos libros, habiendo publicado hasta la fecha cientos de artículos sobre informática e ingeniería en publicaciones especializadas. Microsoft lo ha reconocido como MVP (Most Valuable Professional) en desarrollo web desde el año 2004 hasta la actualidad. Puedes seguirlo en Twitter en @jm_alarcon o leer sus blog técnico o personal. Ver todos los posts de José Manuel Alarcón
Archivado en: Trucos

Boletín campusMVP.es

Solo cosas útiles. Una vez al mes.

🚀 Únete a miles de desarrolladores

DATE DE ALTA

x No me interesa | x Ya soy suscriptor

La mejor formación online para desarrolladores como tú

Comentarios (3) -

Repito un comentario hecho en Facebook para los que como yo, hayan leído el post demasiado rápido ;-)

Esto ... y no será más fácil 'If e.CloseReason = CloseReason.UserClosing Then ' en el evento FormClosing?

Responder

José M. Alarcón
Spain José M. Alarcón

Hola Peni:

La culpa de que no se haya entendido bien es mía porque quizá no he hecho todo el hincapié que debiera en la diferencia que estaba tratando de transmitir, y debería haber mencionado lo de "CloseReason" para mostrarlo más claro, así que muchas gracias por comentar.

La dificultad que trata de mostrar el post, estriba en averiguar si el cierre de la ventana ha sido porque el usuario pulsó sobre el "aspa" de la ventana para cerrar o si ha sido de otra manera (por ejemplo, llamando al método "Close" del formulario desde un botón). Con CloseReason no tienes forma de distinguir estos casos, porque en ambas situaciones devuelve lo mismo: "UserClosing". Con lo explicado en el post podrás distinguir ambos casos fácilmente.

Para verlo más claramente, haz esto: en un formulario arrastras un botón y le pones una llamada al método "Close" del formulario actual para que cierre la ventana. Ahora usa este código:

public partial class Form1 : Form
{
  public const int SC_CLOSE = 0xF060;
  public const int WM_SYSCOMMAND = 0x0112;

  private string motivoCierre = "";

  public Form1()
  {
       InitializeComponent();
  }

  protected override void WndProc(ref System.Windows.Forms.Message m)
  {
      if (m.Msg == WM_SYSCOMMAND && (int)m.WParam == SC_CLOSE)
     {
         motivoCierre += "WndProc: La cerró el usuario\n";
      }
      //La cerró el usuario
      base.WndProc(ref m);
  }

  private void cmdCerrar_Click(object sender, EventArgs e)
  {
       this.Close();
  }

  private void Form1_FormClosing(object sender, FormClosingEventArgs e)
  {
       MessageBox.Show(motivoCierre + "Motivo de cierre en FormClosing: " + e.CloseReason.ToString());
  }
}

Como verás, la ventana de mensaje muestra algo diferente según lo cierres con el aspa o con el botón, y eso es algo imposible de conseguir con CloseReason.

Espero que esto lo aclare mejor.

¡Saludos!

Responder

Excelente. amigo.
me ayudo a poder distinguir cuando el Usuario Cierra (X) y cuando desde un boton ejecuto el metodo this.close


excelente...

Responder

Agregar comentario

Los datos anteriores se utilizarán exclusivamente para permitirte hacer el comentario y, si lo seleccionas, notificarte de nuevos comentarios en este artículo, pero no se procesarán ni se utilizarán para ningún otro propósito. Lee nuestra política de privacidad.