当用户尝试单击使用 Form.ShowDialog() 创建的模态对话框时是否会引发事件?
Is there an event thrown when a user tries to click off a modal dialog created with Form.ShowDialog()?
TL;DR
当 .ShowDialog()
模态对话框打开并且用户单击原始表单时,对话框的标题栏会闪烁。是否可以通过 Windows.Forms
API 或任何其他方式访问该事件?
详情
这是一个标准的 C# 6 Windows Forms 项目,带有一个 parent 表单和一个对话框 window。 parent 表单有一个打开对话框的按钮:
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.");
}
}
}
.ShowDialog(this)
创建的Dialog
同样简单,有一个OK按钮和一个Cancel按钮:
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();
}
}
应用程序启动,
当用户点击 "Show Modal Dialog" 按钮时,button1
事件 Click
被触发,对话框被触发,如第一个片段所示。
当用户在对话框仍然打开的情况下单击原始表单时,对话框的标题栏会闪烁。
是否可以通过 Windows.Forms
API 或任何其他方式访问该事件?
在更复杂的应用程序中,如果对话框的输入字段通过验证,我想在用户单击主窗体时关闭模态对话框,如果没有通过,则突出显示无效字段。
我目前正在使用 .Show()
方法显示 dialog
,并在 deactivate
事件上关闭 dialog
。但这有两个缺点
- 当用户单击桌面或其他应用程序时,
dialog
关闭。
- 当用户单击关闭对话框时,有时主窗体会隐藏在其他应用程序的 window 后面。
我找到了一个 related WPF question,答案非常具体“没有”。
勾选这个post;覆盖 WndProc 方法,它有你需要的所有事件。
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
Console.WriteLine(m.Msg);
}
这可能对您有所帮助。
如 Orion_Eagle 所建议的那样,覆盖 WndProc 是可行的方法。
查看 this list of windows messages
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);
}
TL;DR
当 .ShowDialog()
模态对话框打开并且用户单击原始表单时,对话框的标题栏会闪烁。是否可以通过 Windows.Forms
API 或任何其他方式访问该事件?
详情
这是一个标准的 C# 6 Windows Forms 项目,带有一个 parent 表单和一个对话框 window。 parent 表单有一个打开对话框的按钮:
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.");
}
}
}
.ShowDialog(this)
创建的Dialog
同样简单,有一个OK按钮和一个Cancel按钮:
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();
}
}
应用程序启动,
当用户点击 "Show Modal Dialog" 按钮时,button1
事件 Click
被触发,对话框被触发,如第一个片段所示。
当用户在对话框仍然打开的情况下单击原始表单时,对话框的标题栏会闪烁。
是否可以通过 Windows.Forms
API 或任何其他方式访问该事件?
在更复杂的应用程序中,如果对话框的输入字段通过验证,我想在用户单击主窗体时关闭模态对话框,如果没有通过,则突出显示无效字段。
我目前正在使用 .Show()
方法显示 dialog
,并在 deactivate
事件上关闭 dialog
。但这有两个缺点
- 当用户单击桌面或其他应用程序时,
dialog
关闭。 - 当用户单击关闭对话框时,有时主窗体会隐藏在其他应用程序的 window 后面。
我找到了一个 related WPF question,答案非常具体“没有”。
勾选这个post;覆盖 WndProc 方法,它有你需要的所有事件。
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
Console.WriteLine(m.Msg);
}
这可能对您有所帮助。
如 Orion_Eagle 所建议的那样,覆盖 WndProc 是可行的方法。 查看 this list of windows messages
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);
}