Winforms:在对话框外单击时关闭模式对话框
我有一个开放模式对话框 (Windows窗体)。 我想,在对话框外部(在父窗体上)单击时关闭对话框。 我怎样才能做到这一点?
您应该将其更改为非modal dialog(使用Show(..)
打开它),然后使用Deactivate
事件并关闭它。
这不起作用,您必须使用Show()来触发Deactivate事件。
一个对话框禁用所有其他窗口以使其自身模态。 因此,在父对象最大化的情况下,没有任何内容可以在对话框窗口外单击。 因此,Deactivate事件不会触发。 当您使用Show(所有者)方法时,ShowDialog()的这种副作用不再妨碍并且Deactivate很好。 使用FormClosing / Closed事件执行ShowDialog()调用后的操作。
通常使用上下文菜单条或菜单下拉列表来完成此操作的方法是捕获鼠标Control.Capture属性。 这样您甚至可以在窗口外检测鼠标事件。 但是对于表单无法可靠地工作,表单内的控件将使用Capture属性供自己使用。 坚持使用Show和Deactivate。
有一些原因(例如框架解决方法等)迫使人们使用modal dialog。 您可以通过重写表单方法WndProc
来模拟Deactivate
事件,如下所示:
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
)。 如果您单击父窗体上的某个位置,您的modal dialog将开始“以活动闪烁”告诉您,它现在更重要。 这是通过几次发送前面提到的消息(停用 – >激活 – >停用 – > … – >激活)来实现的。
但要小心,如果handleDeactivate()
方法没有终止您的表单,则每次停用消息时都会调用它。 你必须自己处理。
链接:
MSDN论坛
MSDN文档
使用.Show()代替.ShowDialog()。
以子代码forms处理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; } }
希望这可以帮助。
嗨,我想你可以在事件中使用鼠标按下事件或keydown事件找到鼠标的位置,如果该位置是负值,这意味着你已经选择了窗口的外部区域,然后关闭窗口希望这个帮助。