7

如果用户单击它之外的任何位置,我想关闭 System.Windows.Forms.Form。我尝试过使用 IMessageFilter,但即便如此,也没有任何消息传递给 PreFilterMessage。如何接收表单窗口外的点击?

4

8 回答 8

8

在表单的 Deactivate 事件中,输入“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);

然后在 VolumeSlider 表单的 Deactivate 事件中,您将 this.Close() 如上所述。然后,您的表单将按预期运行。

于 2008-11-18T11:36:51.803 回答
5

感谢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);
}
于 2008-11-19T08:57:51.983 回答
4

使用西蒙的解决方案,我遇到了诺姆描述的相同问题。使用以下代码,我避免了“点击通过”问题...

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();
        }
    }
}
于 2012-07-31T15:10:04.813 回答
1

您应该使用Deactivate
我有一个名为Form2的表单。
在“属性”窗口的“停用”部分。 您声明名称Form2_Deactivate。 在Form2.cs文件中:

private void Form2_Deactivate(object sender, EventArgs e)
{
    this.Close();
}
于 2020-08-27T02:43:36.977 回答
0

如果它是 MDI 应用程序中的子窗体,则可以在父窗体中捕获单击,否则解决方案会很混乱。

无论如何,我不相信您的建议代表直观的 UI 行为。你确定这是最好的设计吗?

于 2008-11-18T11:32:09.377 回答
0

如果您尝试制作一个行为有点像菜单的弹出窗口,除了它允许您与控件交互之外,您可以尝试在工具条下拉列表中托管用户控件。

于 2008-11-18T12:18:47.693 回答
0

简单的方法:在 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
于 2016-12-16T18:35:11.677 回答
0

这很简单:

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();
    }
于 2017-03-17T11:13:03.910 回答