Come chiudo un modulo quando un utente fa clic all'esterno della finestra del modulo?

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

  •  08-07-2019
  •  | 
  •  

Domanda

Voglio chiudere un System.Windows.Forms.Form se l'utente fa clic ovunque al di fuori di esso. Ho provato a utilizzare IMessageFilter, ma anche in questo caso nessuno dei messaggi viene passato a PreFilterMessage. Come faccio a ricevere clic all'esterno della finestra di un modulo?

È stato utile?

Soluzione 2

Grazie a p-daddy in questa domanda , ho trovato questa soluzione che mi permette di usare 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);
}

Altri suggerimenti

Nell'evento Disattiva del modulo, inserisci " this.Close () " ;. Il modulo verrà chiuso non appena si fa clic in qualsiasi altro punto di Windows.

Aggiorna: penso che quello che hai in questo momento sia un pulsante Volume, e all'interno dell'evento Click crei un'istanza del tuo modulo VolumeSlider e lo fai apparire chiamando ShowDialog () che blocca fino a quando l'utente non chiude il modulo pop-up . Nella riga successiva leggi il volume selezionato dall'utente e lo usi nel tuo programma.

Va ??bene, ma come hai notato costringe l'utente a chiudere esplicitamente il popup per tornare al programma principale. Show () è il metodo che vuoi veramente usare qui nel tuo modulo popup, ma Show () non blocca, il che significa che l'evento Click sul tuo modulo principale termina senza sapere quale dovrebbe essere il nuovo volume.

Una soluzione semplice è quella di creare un metodo pubblico nel tuo modulo principale come questo:

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

Quindi, nell'evento Click del pulsante Volume (anche nel modulo principale), fai apparire VolumeSlider in questo modo:

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

Nel modulo VolumeSlider, mentre l'utente lavora sulla barra di scorrimento (suppongo), inserisci questo codice nell'evento ValueChanged della barra di scorrimento (penso che sia quello che è):

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

E poi nell'evento Disattiva del modulo VolumeSlider inseriresti this.Close () come menzionato sopra. Il modulo si comporterà quindi come previsto.

Con la soluzione di Simon ho avuto lo stesso Problema descritto da Noam. Con il seguente codice ho evitato il " Fai clic su " 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 si tratta di un modulo figlio in un'applicazione MDI, è possibile intercettare il clic nel modulo principale, altrimenti la soluzione sarà disordinata.

Non sono convinto che ciò che suggerisci rappresenti comunque un comportamento UI intuitivo. Sei sicuro che sia il miglior design?

Se stai cercando di creare una finestra popup che si comporta in modo un po 'simile a un menu, tranne per il fatto che ti consente di interagire con i tuoi controlli, puoi provare a ospitare un controllo utente all'interno di un menu a discesa della sequenza di strumenti.

MODO SEMPLICE: su Form1 usa questo codice per chiamare form2:

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

e quindi utilizzare nuovamente questo codice su 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

questo è semplice:

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();
    }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top