Winforms:在对话框外单击时关闭模式对话框

问题描述 投票:16回答:5

我有一个开放模式对话框(Windows窗体)。我想,在对话框外部(在父窗体上)单击时关闭对话框。我怎样才能做到这一点?

c# .net winforms modal-dialog
5个回答
25
投票

您应该将其更改为非模态对话框(使用Show(..)打开它),然后使用Deactivate事件并关闭它。


6
投票

这不起作用,您必须使用Show()来触发Deactivate事件。

一个对话框禁用所有其他窗口以使其自身模态。因此,在父对象最大化的情况下,没有任何内容可以在对话框窗口外单击。因此,Deactivate事件不会触发。当您使用Show(所有者)方法时,ShowDialog()的这种副作用不再妨碍并且Deactivate很好。使用FormClosing / Closed事件执行ShowDialog()调用后的操作。

通常使用上下文菜单条或菜单下拉列表来完成此操作的方法是捕获鼠标Control.Capture属性。这样您甚至可以在窗口外检测鼠标事件。但是这对表单无法可靠地工作,表单内的控件将使用Capture属性供自己使用。坚持使用Show和Deactivate。


4
投票

有一些原因(例如框架解决方法等)迫使人们使用模态对话框。您可以通过覆盖表单方法Deactivate来模拟WndProc事件,如下所示:

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

发送WM_NCACTIVATE消息告诉表单指示它是活动的(WParam == 1)还是非活动的(WParam == 0)。如果你点击父窗体上的某个位置,你的模态对话框会开始“闪烁活动”告诉你,现在它更重要。这是通过几次发送前面提到的消息(停用 - >激活 - >停用 - > ... - >激活)来实现的。

但是要小心,如果handleDeactivate()方法没有终止你的表单,每次停用消息时都会调用它。你必须自己处理。

链接: MSDN Forum MSDN Documentation


2
投票

使用.Show()代替.ShowDialog()。

以子代码形式处理Deactivate事件。

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

当用户在孩子外面点击时,这将关闭子表单。

如果您在子项关闭后使用.ShowDialog()执行某些操作,请使用.show()并覆盖父项中child的'formclosing'事件。因此,当儿童表格关闭并在那里做你的东西时会发生。

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

希望这可以帮助。


0
投票

嗨,我想你可以在事件中使用鼠标按下事件或keydown事件找到鼠标的位置,如果该位置是负值,这意味着你已经选择了窗口的外部区域,然后关闭窗口希望这个帮助。

© www.soinside.com 2019 - 2024. All rights reserved.