24

I have an open modal dialog (Windows Forms). I want, that the dialog is closed when clicking outside the dialog (on the parent form). How can I do that?

Kottan
  • 4,944
  • 9
  • 41
  • 67
  • 3
    This smells suspicious to me. Why do you have a *modal* dialog if you want it to be dismissed whenever the user clicks outside of it? The whole point of a modal dialog is that it can't be ignored—an option presented by the dialog must be chosen before the user is allowed to proceed in your application. Chances are, you either need to use a regular non-modal dialog or reconsider your design. – Cody Gray - on strike Dec 22 '10 at 08:56
  • Also, this is an exact duplicate: http://stackoverflow.com/questions/3856301/c-close-modal-form-when-mouse-click-outside-form-area As the answers to that question indicate, you need to capture the mouse to be able to detect those click events. – Cody Gray - on strike Dec 22 '10 at 09:00

6 Answers6

29

You should change it to a non-modal dialog (open it with Show(..)) and then use the Deactivate event and close it.

Elmex
  • 3,331
  • 7
  • 40
  • 64
10

There are reasons (e.g. framework workarounds etc.) which force one to use a modal dialog. You can emulate the Deactivate event by overriding the form method WndProc like this:

protected override void WndProc(ref Message m) {
    const UInt32 WM_NCACTIVATE = 0x0086;

    if (m.Msg == WM_NCACTIVATE && m.WParam.ToInt32() == 0) {
        handleDeactivate();
    } else {
        base.WndProc(ref m);
   }
}

The WM_NCACTIVATE message is send to tell the form to indicate whether it is active (WParam == 1) or inactive (WParam == 0). If you click somewhere on the parent form your modal dialog begins to "blink with activity" telling you, that it is more important right now. This is achieved by sending the previously mentioned Messages a few times (deactivate -> activate -> deactivate -> ... -> activate).

But be careful, if the handleDeactivate() method is not terminating your form, it will be called every time the deactivate messages come. You have to handle that yourself.

Links:
MSDN Forum
MSDN Documentation

pogojotz
  • 452
  • 5
  • 11
6

That cannot work, you must use Show() to get the Deactivate event to fire.

A dialog disables all of the other windows to make itself modal. So there's nothing that can be clicked on outside of the dialog window with the parent maximized. Accordingly, the Deactivate event isn't going to fire. When you use the Show(owner) method instead, this side-effect of ShowDialog() no longer gets in the way and Deactivate is fine. Use the FormClosing/Closed event to do what you would do after a ShowDialog() call.

The way this is normally done, with a context menu strip or menu dropdown for example, is by capturing the mouse, Control.Capture property. So that you can detect mouse events even outside of the window. But that can't work reliably with forms, the controls inside the form will use the Capture property for their own use. So stick with Show and Deactivate.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
3

Use .Show() instead of .ShowDialog().

Handle Deactivate event in child form.

private void frmAdvancedSearch_Deactivate(object sender, EventArgs e)
    {
        this.Close();
    }

This would close the child form when user clicks outside the child.

If you are using .ShowDialog() for doing something after the child closed, use .show() and override the 'formclosing' event of child in the parent. So it would hit when the child form closes and do your stuff there.

advancedSearch.FormClosing += AdvancedSearch_FormClosing;
advancedSearch.ShowDialog();

private void AdvancedSearch_FormClosing(object sender, FormClosingEventArgs e)
    {
        var advanceSearch = sender as frmAdvancedSearch;
        if (advanceSearch.SelectedItem != null)
        {
            myColumnComboBox.Text = advanceSearch.SelectedItem.Name;
        }
    }

Hope this helps.

Ansary Ans21
  • 462
  • 4
  • 6
0

hi I think u can use the mouse down event or keydown event in the event find the location fo the mouse if that location is in minus values that means u have selected the outer area of the windows and then close that windows hope this help.

JSJ
  • 5,653
  • 3
  • 25
  • 32
0

You can use this.ParentForm.MouseClick += ParentForm_MouseClick and also

this.ParentForm.Click += ParentForm_Click

and then Close your form.

private void ParentForm_MouseClick(object sender, MouseEventArgs e)
{
   this.Close();
}
Grigory Zhadko
  • 1,484
  • 1
  • 19
  • 33