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

Kot*_*tan 17 .net c# modal-dialog winforms

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

Elm*_*mex 26

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


Han*_*ant 6

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

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

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


pog*_*otz 5

有一些原因(例如框架变通办法等)迫使人们使用模式对话框。您可以Deactivate通过重写form方法来模拟事件,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);
   }
}
Run Code Online (Sandbox Code Playgroud)

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

但是请注意,如果该handleDeactivate()方法没有终止您的表单,则每次停用消息出现时都会调用该方法。您必须自己处理。

链接:
MSDN论坛
MSDN文档