Comment fermer un formulaire lorsqu'un utilisateur clique en dehors de la fenêtre du formulaire?

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

  •  08-07-2019
  •  | 
  •  

Question

Je souhaite fermer un objet System.Windows.Forms.Form si l'utilisateur clique en dehors de celui-ci. J'ai essayé d'utiliser IMessageFilter, mais même dans ce cas, aucun des messages n'est transmis à PreFilterMessage. Comment recevoir des clics en dehors de la fenêtre d'un formulaire?

Autres conseils

Dans l'événement Deactivate de votre formulaire, insérez "this.Close ()". Votre formulaire se ferme dès que vous cliquez n'importe où dans Windows.

Mise à jour: je pense que vous avez maintenant un bouton de volume. Dans l'événement Click, vous créez une instance de votre formulaire VolumeSlider et le faites apparaître en appelant ShowDialog (), qui bloque jusqu'à ce que l'utilisateur ferme le formulaire affiché. . Dans la ligne suivante, lisez le volume sélectionné par l'utilisateur et utilisez-le dans votre programme.

Ce n’est pas un problème, mais comme vous l’avez remarqué, cela oblige l’utilisateur à fermer explicitement la fenêtre afin de revenir au programme principal. Show () est la méthode que vous voulez vraiment utiliser ici dans votre formulaire contextuel, mais Show () ne bloque pas, ce qui signifie que l'événement Click revient sur votre formulaire principal se termine sans savoir ce que le nouveau volume est censé être.

Une solution simple consiste à créer une méthode publique sur votre formulaire principal, comme suit:

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

Ensuite, dans l'événement Click de votre bouton Volume (également sur le formulaire principal), vous donnez à VolumeSlider l'apparence suivante:

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

Dans le formulaire VolumeSlider, lorsque l'utilisateur utilise la barre de défilement (je suppose), vous insérez ce code dans l'événement ValueChanged de la barre de défilement (je pense que c'est bien ce qu'il est):

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

Ensuite, dans l'événement Deactivate du formulaire VolumeSlider, placez this.Close () comme indiqué ci-dessus. Votre formulaire se comportera alors comme prévu.

Avec la solution de Simon, j'avais le même problème décrit par Noam. Avec le code suivant, j'ai évité les " Click through " problème ...

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();
        }
    }
}

S'il s'agit d'un formulaire enfant dans une application MDI, vous pouvez intercepter le clic dans le formulaire parent, sinon la solution sera désordonnée.

De toute façon, je ne suis pas convaincu que ce que vous suggérez représente un comportement intuitif de l'interface utilisateur. Etes-vous sûr que c'est le meilleur design?

Si vous essayez de créer une fenêtre contextuelle qui se comporte un peu comme un menu, si ce n'est qu'elle vous permet d'interagir avec vos contrôles, vous pouvez essayer d'héberger un contrôle utilisateur dans une liste déroulante de la barre d'outils.

FAIRE SIMPLEMENT: sur Form1, utilisez ce code pour appeler form2:

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

puis utilisez à nouveau ce code sur form1:

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

c'est 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();
    }
scroll top