Como faço para fechar um formulário quando um usuário clica fora da janela do formulário?

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

  •  08-07-2019
  •  | 
  •  

Pergunta

Eu quero fechar uma System.Windows.Forms.Form se o usuário clica em qualquer lugar fora dela. Eu tentei usar IMessageFilter, mas, mesmo assim, nenhuma das mensagens são passadas para PreFilterMessage. Como faço para receber cliques fora da janela de um formulário?

Foi útil?

Solução 2

Com graças a p-daddy em este pergunta, eu encontrei esta solução 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);
}

Outras dicas

No evento Desactivar do formulário, colocar "this.Close ()". Sua forma vai perto, logo que você clique em qualquer outro lugar no Windows.

Update: Eu acho que o que você tem agora é um botão de volume, e dentro do evento Click você cria uma instância do seu formulário volumeSlider e fazer parecer chamando ShowDialog (), que bloqueia até que o usuário fecha o formulário bateu-se . Na linha seguinte você ler o volume do usuário selecionado e usá-lo em seu programa.

Este é OK, mas como você percebeu que força o usuário a fechar explicitamente o pop-up, a fim de voltar para o programa principal. Show () é o método que você realmente quer usar aqui na sua forma de pop-up, mas Show () não bloqueia o que significa que o evento volta clicar em seus principais acabamentos de formulário sem saber o que o novo volume é suposto ser.

Uma solução simples é criar um método público em seu formulário principal como esta:

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

Então, em do seu botão de volume evento Click (também no formulário principal), você faz o volumeSlider aparecem assim:

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

Na forma volumeSlider, como o usuário trabalha o (eu acho) barra de rolagem, você colocar esse código no evento ValueChanged da barra de rolagem (eu acho que é o que é):

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

E, em seguida, no evento Desactivar do formulário volumeSlider você colocaria this.Close () como mencionado acima. Sua forma, então, se comportam como esperado.

Com a solução da Simon Eu tive o mesmo problema describt por Noam. Com seguinte código que eu evitar o "click through" 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();
        }
    }
}

Se for um formulário filho em um aplicativo MDI, você poderia prender o clique no formulário pai, caso contrário, a solução será confuso.

Não estou convencido que você sugere representa um comportamento interface intuitiva de qualquer maneira. Tem certeza que é o melhor design?

Se você está tentando fazer com que uma janela pop-up que se comporta um pouco como um menu, exceto que ele permite que você interaja com seus controles, você pode tentar hospedando um UserControl dentro de um menu suspenso toolstrip.

simplesmente a maneira: no Form1 usar este código para chamar form2:

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

e, em seguida, usar esse código em form1 novamente:

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

isso é simples:

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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top