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

En Visual Basic 6 era muy fácil hacerlo dentro del evento QueryUnload gracias al parámetro UnloadMode. Sin embargo en .NET no es tan sencillo averiguarlo. Hoy nos ha surgido la necesidad en un trabajo y lo cierto es que no tenía ni idea ya que suelo trabajar más con WebForms, que no se cierran ;-)

Aunque no es tan flexible como el evento QueryUnload mencionado esta solución hace el trabajo.

Se trata de subclasificar el procedimiento de la ventana (mira mi post sobre Subclasificación de ventanas en .NET) y verificar que el mensaje que se está produciendo es WM_SYSCOMMAND con el parámetro SC_CLOSE, así:

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).

Escrito por un humano, no por una IA