当用户尝试单击使用Form.ShowDialog()创建的模式对话框时,会引发事件吗?

kdb*_*man 5 c# events modal-dialog winforms

TL; DR

.ShowDialog()打开模式对话框并且用户单击原始表单时,对话框的标题栏闪烁。是否可以通过Windows.FormsAPI或其他任何方式访问该事件?


细节

这是带有父窗体和对话框窗口的标准C#6 Windows Forms项目。父表单只有一个按钮可以打开对话框:

using System;
using System.Windows.Forms;

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        using (var dialog = new Dialog())
        {
            Console.WriteLine("Dialog starting.");

            dialog.ShowDialog(this);

            Console.WriteLine("Dialog done.");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Dialog由创建.ShowDialog(this)同样简单,与OK按钮和取消按钮:

using System;
using System.Windows.Forms;

public partial class Dialog : Form
{
    public Dialog()
    {
        InitializeComponent();
    }

    private void btnOK_Click(object sender, EventArgs e)
    {
        Close();
    }

    private void btnCancel_Click(object sender, EventArgs e)
    {
        Close();
    }
}
Run Code Online (Sandbox Code Playgroud)

该应用程序启动,

在此处输入图片说明

当用户单击“显示模态对话框”按钮时,将触发该button1事件Click,并如第一个代码片段所示触发该对话框。

在此处输入图片说明

当用户在对话框仍处于打开状态时单击原始表单时,对话框的标题栏将闪烁。

在此处输入图片说明

是否可以通过Windows.FormsAPI或其他任何方式访问该事件?

在更复杂的应用程序中,如果对话框的输入字段通过了验证,那么用户单击主窗体时,我想关闭模式对话框,如果没有通过验证,则突出显示无效的字段。

我目前显示了dialog使用.Show()方法,并关闭dialogdeactivate事件。但这有两个缺点

  • 当用户单击桌面或其他应用程序时,将dialog关闭。
  • 当用户单击对话框时,有时主窗体隐藏在其他应用程序窗口的后面。

我找到了一个有关WPF的问题,答案是一个非常具体的“ ”。

小智 3

正如 Orion_Eagle 所建议的,重写 WndProc 是可行的方法。查看此 Windows 消息列表

protected override void WndProc(ref Message m)
{
    //134 = WM_NCACTIVATE
    if (m.Msg == 134)
    {       
        //Check if other app is activating - if so, we do not close         
        if (m.LParam == IntPtr.Zero)
        {                    
             if (m.WParam != IntPtr.Zero)
             {                     
                 //Other form in our app has focus
             }

        }
     }                     

     base.WndProc(ref m);
}
Run Code Online (Sandbox Code Playgroud)