BUG: You may receive a StackOverflowException exception when you make a child MDI form visible in Visual Studio .NET 2003 and in Visual Studio .NET 2002 (893710)



The information in this article applies to:

  • Microsoft Visual Studio .NET (2003), Professional Edition
  • Microsoft Visual Studio .NET (2003), Enterprise Architect Edition
  • Microsoft Visual Studio .NET (2003), Enterprise Developer Edition
  • Microsoft Visual Studio .NET (2003), Academic Edition
  • Microsoft Visual Studio .NET (2002), Professional Edition
  • Microsoft Visual Studio .NET (2002), Professional Edition SP1
  • Microsoft Visual Studio .NET (2002), Enterprise Architect Edition
  • Microsoft Visual Studio .NET (2002), Enterprise Architect Edition SP1
  • Microsoft Visual Studio .NET (2002), Enterprise Developer Edition
  • Microsoft Visual Studio .NET (2002), Enterprise Developer Edition SP1
  • Microsoft Visual Studio .NET (2002), Academic Edition

SYMPTOMS

In Microsoft Visual Studio .NET 2003 and in Microsoft Visual Studio .NET 2002, you may receive a StackOverflowException exception when the following conditions are true:
  • You make a child multiple-document interface (MDI) form visible.
  • The parent MDI form is not visible.

CAUSE

This problem occurs when the parent form of a child MDI form has the Visible property set to false, and you call the Show method of the child MDI form.

WORKAROUND

To work around this problem, make sure that all the parent forms and controls are visible before you call the Show method of the child MDI form.

For example, you can create a method that recurses through all parent forms and examines the Visible property. The following lines of code demonstrate how you create this method.
private bool allParentsVisible(Control ctl)
{
	ctl = ctl.Parent;
	while (ctl != null)
	{
		if (!ctl.Visible)
		{
			return false;
		}
		ctl = ctl.Parent;
	}
	return true;
}
Note This code is also in the code example in step 8 of the "Steps to reproduce the problem" section.

Call the allParentsVisible method before you make the child MDI form visible by using the following lines of code.
	private void btnCheckVisible_Click(object sender, System.EventArgs e)
		{
			pForm.Visible = false;

			// Clearly this will not show the form because the visibility of the parent is false.
			// However, in a "real world" application you may not know where the parent form's visibility is 
			// changed.  This is one way to help protect against that.
			if (allParentsVisible(cForm))
				cForm.Show();

		}
	

STATUS

Microsoft has confirmed that this is a bug in the Microsoft products that are listed in the "Applies to" section.

MORE INFORMATION

Steps to reproduce the problem

  1. Start Visual Studio .NET.
  2. Create a new Microsoft Windows application that is named Q893710.
  3. In Solution Explorer, right-click the application, point to Add, and then click Add Windows Form.
  4. Name the new form parentForm.
  5. In Solution Explorer, right-click the application, point to Add, and then click Add Windows Form.
  6. Name the new form childForm.
  7. Right-click Form1, and then click View code.
  8. Replace all the code in Form1 with the following lines of code.
    using System;
    using System.Drawing;
    using System.Collections;
    using System.ComponentModel;
    using System.Windows.Forms;
    
    namespace Q893710
    {
    	/// <summary>
    	/// Summary description for Form1.
    	/// </summary>
    	public class Form1 : System.Windows.Forms.Form
    	{
    		private parentForm pForm;
    		private childForm cForm;
    		private System.Windows.Forms.Button btnOverflow;
    		private System.Windows.Forms.Button btnCreateForms;
    		private System.Windows.Forms.Button btnCheckVisible;
    
    		/// <summary>
    		/// Required designer variable.
    		/// </summary>
    		private System.ComponentModel.Container components = null;
    
    		public Form1()
    		{
    			InitializeComponent();
    		}
    
    		protected override void Dispose( bool disposing )
    		{
    			if( disposing )
    			{
    				if(components != null)
    				{
    					components.Dispose();
    				}
    			}
    			base.Dispose( disposing );
    		}
    
    			private void InitializeComponent()
    		{
    			this.btnCreateForms = new System.Windows.Forms.Button();
    			this.btnOverflow = new System.Windows.Forms.Button();
    			this.btnCheckVisible = new System.Windows.Forms.Button();
    			this.SuspendLayout();
    			// 
    			// btnCreateForms
    			// 
    			this.btnCreateForms.Location = new System.Drawing.Point(8, 24);
    			this.btnCreateForms.Name = "btnCreateForms";
    			this.btnCreateForms.Size = new System.Drawing.Size(112, 23);
    			this.btnCreateForms.TabIndex = 0;
    			this.btnCreateForms.Text = "1. Create forms";
    			this.btnCreateForms.Click += new System.EventHandler(this.btnCreateForms_Click);
    			// 
    			// btnOverflow
    			// 
    			this.btnOverflow.BackColor = System.Drawing.Color.Red;
    			this.btnOverflow.Location = new System.Drawing.Point(160, 240);
    			this.btnOverflow.Name = "btnOverflow";
    			this.btnOverflow.Size = new System.Drawing.Size(120, 23);
    			this.btnOverflow.TabIndex = 1;
    			this.btnOverflow.Text = "STACK OVERFLOW";
    			this.btnOverflow.Click += new System.EventHandler(this.btnOverflow_Click);
    			// 
    			// btnCheckVisible
    			// 
    			this.btnCheckVisible.Location = new System.Drawing.Point(8, 56);
    			this.btnCheckVisible.Name = "btnCheckVisible";
    			this.btnCheckVisible.Size = new System.Drawing.Size(112, 23);
    			this.btnCheckVisible.TabIndex = 2;
    			this.btnCheckVisible.Text = "2. Check all visible";
    			this.btnCheckVisible.Click += new System.EventHandler(this.btnCheckVisible_Click);
    			// 
    			// Form1
    			// 
    			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
    			this.ClientSize = new System.Drawing.Size(292, 273);
    			this.Controls.Add(this.btnCheckVisible);
    			this.Controls.Add(this.btnOverflow);
    			this.Controls.Add(this.btnCreateForms);
    			this.Name = "Form1";
    			this.Text = "Form1";
    			this.ResumeLayout(false);
    
    		}
    	
    
    
    
    
    		private bool allParentsVisible(Control ctl)
    		{
    			ctl = ctl.Parent;
    			while (ctl != null)
    			{
    				if (!ctl.Visible)
    				{
    					return false;
    				}
    				ctl = ctl.Parent;
    			}
    			return true;
    		}
    
    
    		private void btnOverflow_Click(object sender, System.EventArgs e)
    		{
    			//This is bad. Create a stack overflow.
    			pForm.Visible = false;
    			cForm.Show();
    		}
    
    		private void btnCreateForms_Click(object sender, System.EventArgs e)
    		{
    			pForm		= new parentForm();
    			pForm.IsMdiContainer	= true;
    
    			cForm			= new childForm();
    			cForm.MdiParent			= pForm;
    
    			// Show the parent form.
    			pForm.Show();
    		}
    
    		private void btnCheckVisible_Click(object sender, System.EventArgs e)
    		{
    			pForm.Visible = false;
    
    			// Clearly this will not show the form because the visibility of the parent is false.
    			// However, in a "real world" application you may not know where the parent form's visibility is 
    			// changed.  This is one way to help protect against that.
    			if (allParentsVisible(cForm))
    				cForm.Show();
    
    		}
    
    		static void Main() 
    	        {
    		Application.Run(new Form1());
    	        }         
          }
    }
  9. Click Start.
  10. In the compiled application, click STACK OVERFLOW. You receive a StackOverflowException exception.
Note Make sure that the namespace of Form1 matches the namespace of childForm and of parentForm.

Modification Type:MinorLast Reviewed:9/13/2005
Keywords:kbvs2002sp1sweep kbtshoot kbbug KB893710 kbAudDeveloper kbAudITPRO