Как закрыть форму, когда пользователь щелкает за пределами окна формы?

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

  •  08-07-2019
  •  | 
  •  

Вопрос

Я хочу закрыть System.Windows.Forms.Form, если пользователь щелкнет где-нибудь за ее пределами. Я пытался использовать IMessageFilter, но даже тогда ни одно из сообщений не было передано в PreFilterMessage. Как получить клики за пределами окна формы?

Это было полезно?

Решение 2

Благодаря p-daddy в этот вопрос , я нашел это решение, которое позволяет мне использовать 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);
}

Другие советы

В событии "Деактивировать" формы укажите "this.Close ()". Ваша форма закроется, как только вы нажмете где-нибудь еще в Windows.

Обновление: я думаю, что у вас есть кнопка громкости, и внутри события Click вы создаете экземпляр формы VolumeSlider и отображаете его, вызывая ShowDialog (), который блокируется, пока пользователь не закроет всплывающую форму. , В следующей строке вы читаете том, выбранный пользователем, и используете его в своей программе.

Это нормально, но, как вы заметили, это заставляет пользователя явно закрывать всплывающее окно, чтобы вернуться в основную программу. Show () - это метод, который вы действительно хотите использовать здесь во всплывающей форме, но Show () не блокирует, что означает, что событие Click на главной форме завершается, не зная, каким должен быть новый том.

Простое решение состоит в том, чтобы создать публичный метод в главной форме, например так:

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

Затем в событии Click вашей кнопки громкости (также в главной форме) вы заставляете VolumeSlider выглядеть следующим образом:

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

В форме VolumeSlider, когда пользователь работает (я думаю) с полосой прокрутки, вы помещаете этот код в событие ValueChanged на полосе прокрутки (я думаю, что это именно так):

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

А затем в событии Deactivate формы VolumeSlider вы должны поместить this.Close (), как указано выше. Ваша форма будет вести себя как положено.

С решением Саймона у меня была та же проблема, описанная Ноамом. С помощью следующего кода я избегаю " Нажмите через " проблема ...

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

Если это дочерняя форма в приложении MDI, вы можете перехватить щелчок в родительской форме, иначе решение будет грязным.

Я не уверен, что то, что вы предлагаете, представляет интуитивное поведение пользовательского интерфейса. Вы уверены, что это лучший дизайн?

Если вы пытаетесь создать всплывающее окно, похожее на меню, за исключением того, что оно позволяет вам взаимодействовать с вашими элементами управления, вы можете попробовать разместить пользовательский контроль в раскрывающемся списке инструментов.

ПРОСТОЙ ПУТЬ: в Form1 используйте этот код для вызова form2:

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

, а затем снова используйте этот код в 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

это просто:

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();
    }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top