即使form3是从form2创建的,为什么它不会在form2上关闭?

时间:2009-12-08 07:01:43

标签: winforms

我需要你的帮助来澄清表单是否与对象完全相同?

如果我从另一个对象obj1创建一个obj2对象。 obj2将在obj1处置。

然而形式并非如此。 查看案例&伪代码在下面给出。

我有三种形式; form1,form2&窗口2。

form1是启动表单。 form1将创建一个form2和from2将如何创建&使用每种形式的按钮显示form3。

如果我关闭form2,打开所有3个表单后,我可以在form1和form3中工作。

我的问题是即使form3是从form2创建的,为什么它不会在form2上关闭?

Form1中


Public Class Form1
Private Sub cmdOpenForm2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdOpenForm2.Click
  Dim frm As New Form2
  With frm
   ''/.MdiParent = frmMain
   .Show()
   .BringToFront()
  End With
End Sub

 Private Sub Form1_Disposed(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Disposed
  ''//frmMain.tsStatus.Text = "Form1 disposed"
 End Sub
End Class

窗体2


Public Class Form2
 Private Sub cmdRandomColor_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdRandomColor.Click
  Randomize()
  Label1.ForeColor = Color.FromArgb(Rnd() * 255, Rnd() * 255, Rnd() * 255, Rnd() * 255)
 End Sub

 Private Sub Form2_Disposed(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Disposed
  frmMain.tsStatus.Text = "Form2 disposed"
 End Sub

 Private Sub cmdOpenForm3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdOpenForm3.Click
  Dim frm As New Form3
  With frm
   ''//.MdiParent = frmMain
   .Show()
   .BringToFront()
  End With
 End Sub
 End Class

Form3


Public Class Form3
 Private Sub cmdRandomColor_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdRandomColor.Click
  Randomize()
  Label1.ForeColor = Color.FromArgb(Rnd() * 255, Rnd() * 255, Rnd() * 255, Rnd() * 255)
 End Sub

 Private Sub Form3_Disposed(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Disposed
  frmMain.tsStatus.Text = "Form3 disposed"
 End Sub
End Class

非常感谢任何帮助。

修改 谢谢大家的解决方案

很抱歉提及,我不是在寻找解决方案如何在form2关闭处理form3。

我感兴趣的是背后发生的事情......是否有可能从2创建的form3实例获得GC收集并且我得到内存错误。

因为我在我的实际应用程序中获得了保护内存访问异常,这个异常设计不合适,而且现在重构太大了。

我的问题是在哪里创建了form3实例?是在Form2实例中还是在其他地方。 因为我可以在form2处理后访问form3实例。我怀疑它是在其他地方创建的

6 个答案:

答案 0 :(得分:1)

Dispose调用与您自己创建的新表单相关的表单上没有任何自动发生。

如果您希望表单自动处理它创建的表单,您必须自己添加代码才能执行此操作。找到设计器添加的.Dispose方法,并将其添加到那里,或者在表单上实现FormClosed事件。

form2“创建”form1并不会在两者之间形成任何关系。

答案 1 :(得分:1)

可选择自动处理。表格必须是“拥有”的表格。最简单的方法是使用Form.Show(owner)重载:

private void button1_Click(object sender, EventArgs e) {
  new Form3().Show(this);
}

或者您可以使用Form.AddOwnedForm()方法执行此操作。请注意,这有副作用,拥有的表格始终显示在所有者面前。它将与业主一起最小化并恢复。如果您不想这样做,您可以明确跟踪表单的生命周期并自行处理:

private Form3 mForm3;

private void button1_Click(object sender, EventArgs e) {
  if (mForm3 == null) {
    mForm3 = new Form3();
    mForm3.FormClosed += (s, ea) => mForm3 = null;
    mForm3.Show();
  }
  else {
    mForm3.WindowState = FormWindowState.Normal;
    mForm3.Focus();
  }
}

protected override void OnFormClosed(FormClosedEventArgs e) {
  if (mForm3 != null) mForm3.Dispose();
}

答案 2 :(得分:0)

  

如果我从另一个对象obj1创建一个obj2对象。 obj2将在obj1处置。

不一定。如果某个其他对象(例如obj3)引用了obj2,那么obj2即使在obj1被垃圾回收后仍会存在。

在这种情况下,窗口管理器引用了form3,因此即使form2是,也不会进行垃圾回收。

答案 3 :(得分:0)

您必须使用以Win32-Window-Handle作为参数的Form-Constructor。您可以将form2的引用传递给form3然后它可以按预期工作。

Private Sub cmdOpenForm2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdOpenForm2.Click
  Dim frm As New Form2(Me)
  With frm
   .Show()
   .BringToFront()
  End With
End Sub

答案 4 :(得分:0)

如果您将表单变量更改为实例变量,并将其包含在Show方法中,它将起作用

Form1的代码

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

        private void button1_Click(object sender, EventArgs e)
        {
            f = new Form2();
            f.Show(this);
        }

        private void button2_Click(object sender, EventArgs e)
        {
            f.Close();
            f = null;
        }
    }

Form2的代码

public partial class Form2 : Form
    {
        Form3 f;
        public Form2()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            f = new Form3();
            f.Show(this);
        }
    }

答案 5 :(得分:0)

框架仍然保持着你的表单对象,直到它被关闭。您可以使用My.Application.OpenForms获取对它的引用。