¿Cómo cierro un formulario cuando un usuario hace clic fuera de la ventana del formulario?

StackOverflow https://stackoverflow.com/questions/298491

  •  08-07-2019
  •  | 
  •  

Pregunta

Quiero cerrar un System.Windows.Forms.Form si el usuario hace clic en cualquier lugar fuera de él. Intenté usar IMessageFilter, pero aun así ninguno de los mensajes se pasa a PreFilterMessage. ¿Cómo recibo clics fuera de la ventana de un formulario?

¿Fue útil?

Solución 2

Gracias a p-daddy en esta pregunta , he encontrado esta solución que me permite usar ShowDialog:

protected override void OnShown(EventArgs e)
{
    base.OnShown(e);
    this.Capture = true;
}

protected override void OnCaptureChanged(EventArgs e)
{
    if (!this.Capture)
    {
        if (!this.RectangleToScreen(this.DisplayRectangle).Contains(Cursor.Position))
        {
            this.Close();
        }
        else
        {
            this.Capture = true;
        }
    }

    base.OnCaptureChanged(e);
}

Otros consejos

En el evento Desactivar de su formulario, ponga " this.Close () " ;. Su formulario se cerrará tan pronto como haga clic en cualquier otro lugar de Windows.

Actualización: Creo que lo que tienes ahora es un botón de Volumen, y dentro del evento Click creas una instancia de tu formulario VolumeSlider y lo haces aparecer llamando a ShowDialog () que bloquea hasta que el usuario cierra el formulario emergente . En la línea siguiente, lee el volumen que seleccionó el usuario y lo usa en su programa.

Esto está bien, pero como ha notado, obliga al usuario a cerrar explícitamente la ventana emergente para volver al programa principal. Show () es el método que realmente desea utilizar aquí en su formulario emergente, pero Show () no bloquea, lo que significa que el evento Click en su formulario principal finaliza sin saber cuál se supone que es el nuevo volumen.

Una solución simple es crear un método público en su formulario principal como este:

public void SetVolume(int volume)
{
    // do something with the volume - whatever you did before with it
}

Luego, en el evento Click del botón Volumen (también en el formulario principal), hace que el Control deslizante de volumen aparezca así:

VolumeSlider slider = new VolumeSlider();
slider.Show(this); // the "this" is needed for the next step

En el formulario VolumeSlider, a medida que el usuario trabaja la barra de desplazamiento (supongo), coloca este código en el evento ValueChanged de la barra de desplazamiento (creo que eso es lo que es):

MainForm owner = (MainForm)this.Owner;
owner.SetVolume(scrollbar.Value);

Y luego, en el evento Desactivar del formulario VolumeSlider, colocaría esto. Close () como se mencionó anteriormente. Su formulario se comportará como se esperaba.

Con la solución de Simon tuve el mismo problema descrito por Noam. Con el siguiente código, evito el " Haga clic en " problema ...

protected override void WndProc(ref Message m)
{    
    base.WndProc(ref m);

    // if click outside dialog -> Close Dlg
    if (m.Msg == NativeConstants.WM_NCACTIVATE) //0x86
    {
        if (this.Visible)
        {
            if (!this.RectangleToScreen(this.DisplayRectangle).Contains(Cursor.Position))
                this.Close();
        }
    }
}

Si se trata de un formulario secundario en una aplicación MDI, puede atrapar el clic en el formulario principal, de lo contrario, la solución será complicada.

No estoy convencido de que lo que sugiera represente un comportamiento intuitivo de la IU de todos modos. ¿Estás seguro de que es el mejor diseño?

Si está intentando crear una ventana emergente que se comporte un poco como un menú, excepto que le permite interactuar con sus controles, puede intentar alojar un control de usuario dentro de un menú desplegable de herramientas.

SIMPLEMENTE MANERA: en Form1 use este código para llamar a form2:

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles     Button1.Click
    Form2.Owner = Me
    Form2.Show()
End Sub

y luego use este código en form1 nuevamente:

Private Sub Form1_MouseClick(sender As Object, e As MouseEventArgs) Handles Me.MouseClick
    If Form2.IsHandleCreated = True Then
        Form2.Close()
    End If
End Sub

esto es simple:

private void button1_Click(object sender, EventArgs e)
    {
        Form f = new Form();
        f.LostFocus +=new EventHandler(f_LostFocus);
        f.Show();
    }

    void f_LostFocus(object sender, EventArgs e)
    {
        Form f = sender as Form;
        f.Close();
        f.Dispose();
    }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top