图片 http://img225.imageshack.us/img225/1075/modalnonmodalproblem.png
图片 http://img225.imageshack.us/img225/1075/modalnonmodalproblem.png
模态窗体完全按照“模态”的含义执行,它们会禁用应用程序中的所有其他窗口。这非常重要,因为您的程序处于一种相当危险的状态。您有一块代码正在等待对话框关闭。如果那些其他窗口没有被禁用,可能会发生非常糟糕的事情。比如用户可能会再次启动模态对话框,现在您的代码嵌套了两次。或者她可能关闭对话框的所有者窗口,使其突然消失。
如果您在循环内部调用Application.DoEvents(),也会遇到这些完全相同的问题。这是一种在不禁用其他窗口的情况下使窗体模态化的方法之一。例如:
Form2 mDialog;
private void button1_Click(object sender, EventArgs e) {
mDialog = new Form2();
mDialog.FormClosed += (o, ea) => mDialog = null;
mDialog.Show(this);
while (mDialog != null) Application.DoEvents();
}
这很危险。
最好按照模态窗体的设计来使用它们,以避免麻烦。如果您不想要模态窗体,那么只需不将其设置为模态,并使用Show()方法。订阅其FormClosing事件以了解它即将关闭:
private void button1_Click(object sender, EventArgs e) {
var frm = new Form2();
frm.FormClosing += new FormClosingEventHandler(frm_FormClosing);
frm.Show();
}
void frm_FormClosing(object sender, FormClosingEventArgs e) {
var frm = sender as Form2;
// Do something with <frm>
//...
}
在我看来,您可以使用一个 MDI 应用程序,并将窗体 #0 的 IsMdiContainer 属性设置为 true。
然后,您可以执行类似以下的操作:
public partial class Form0 {
public Form0 {
InitializeComponent();
this.IsMdiContainer = true; // This will allow the Form #0 to be responsive while other forms are opened.
}
private void button1_Click(object sender, EventArgs e) {
Form1 newForm1 = new Form1();
newForm1.Parent = this;
newForm1.Show();
}
}
在你的问题中,使用ShowDialog()会使所有表单Modal = true。
按照定义,模态窗体是这样的:
当以模态形式显示一个窗体时,除了模态窗体上的对象外,不能进行任何输入(键盘或鼠标点击)。程序必须在允许跳转到另一个窗体之前隐藏或关闭一个模态窗体(通常是响应某些用户操作)。通常将以模态形式显示的窗体用作应用程序中的对话框。
您可以使用此属性 [(Modal)] 来确定从方法或属性获取的窗体是否已以模态方式显示。
因此,仅当您需要立即获得用户的帮助/交互时才应使用模态窗体。否则,使用模态窗体会使人误以为您可能正在错误的方向上运行。
如果您不想让主窗体成为MDI容器,那么也许使用多线程是一个解决方案,通过简单的BackgroundWorker类是实现您想要达到的关键。因此,在我看来,这似乎是一种设计上的问题...
解释您必须做什么,我们也许能够共同指导您朝着正确的方向,或者至少是更好的方向。
在同一进程空间中的任何模态对话框关闭之前,您的主窗体将不会响应。这方面没有解决办法。
实际上答案非常简单。尝试一下。
newForm.showDialog();
这将打开一个新的窗体,而父窗体将无法访问。