Does anyone know if this is possible, and if so, how to do it?

I want to open a child form within an MDI parent. If I close that form, then open it again, it's position is offset (as if cascading). Is there some way to preset (or reset) the position a child form occupies when opened subsequent times? The child form(s) in this case is not a document, but a form with data entry fields on it.

Perhaps I'm going about this the wrong way. I want to be able to open, close and reopen any of several forms within an "main" window and control their positions upon opening/reopening. I can do this (control positioning) if I don't use MDI, but I don't want these forms to exist outside the "main" form.

Dani AI

Generated

Short summary and a practical pattern you can drop into the MDI parent. The shifting you see is the default placement behavior for new MDI children; the reliable fix is to give each child a Manual start position and explicitly restore (or set) its Location when you create it. Below are two small, complete VB.NET helpers: one reuses an existing child (bring-to-front) and one saves the last closed location per form type so reopened instances show where the user left them.

' In the MDI parent form
Private lastPositions As New Dictionary(Of String, Point)()

Private Function FindOpenChild(Of T As Form)() As T
    For Each f As Form In Me.MdiChildren
        If TypeOf f Is T Then Return DirectCast(f, T)
    Next
    Return Nothing
End Function

Private Sub OpenChild(Of T As {Form, New})()
    Dim key = GetType(T).FullName
    Dim child As T = FindOpenChild(Of T)()
    If child Is Nothing Then
        child = New T()
        child.MdiParent = Me
        child.StartPosition = FormStartPosition.Manual
        If lastPositions.ContainsKey(key) Then
            child.Location = lastPositions(key)
        Else
            child.Location = New Point(16, 16) ' default inside MDI client
        End If
        AddHandler child.FormClosed, AddressOf Child_FormClosed
        child.Show()
    Else
        child.Activate()
    End If
End Sub

Private Sub Child_FormClosed(sender As Object, e As FormClosedEventArgs)
    Dim f As Form = DirectCast(sender, Form)
    lastPositions(f.GetType().FullName) = f.Location
    RemoveHandler f.FormClosed, AddressOf Child_FormClosed
End Sub

Notes and tips: call this from menu/buttons instead of creating new instances directly. If a child sometimes repositions after Show, set Location in its Shown handler or ensure its WindowState is Normal first. This approach builds on ’s idea of detecting existing children and on ’s per-form-position tracking, but implements a compact, type-safe VB.NET solution and avoids destroying form state if you prefer to reuse instances. If you want permanent persistence across app runs, serialize the dictionary to settings or a file.

Recommended Answers

All 6 Replies

in your case it is cascading!

Yes, I KNOW it's cascading, even if there are no other forms being opened. Each instance of the same form is positioned as if the other instances are still present. I used "as if" because this behavior seems counter-intuitive, since a single form doesn't need to cascade.

I know what's happening; what I need to know is how to prevent it.

Yes, I KNOW it's cascading, even if there are no other forms being opened. Each instance of the same form is positioned as if the other instances are still present. I used "as if" because this behavior seems counter-intuitive, since a single form doesn't need to cascade.

I know what's happening; what I need to know is how to prevent it.

I know what you trying to do and have been searching for a solution to my problem also but you can try setting your child forms "FormBorderStyle" to none and "Location" to 0,0 with Start Position to Manual. That'll display the Child form at the top of your form window.

The problem I have is closing the Child upon opening a new child. Any idea's?

I created the following two methods
First one checks if the Child for is currently open and if so I call the second one that closes it, you can also just modify it to bring the child form to front

private bool ContainsChildForm(Type t)
        {   
            for (int i = 0; i < this.MdiChildren.Length; i++)   
            {       
                if (t.IsInstanceOfType(this.MdiChildren[i]))       
                {       
                    return true;       
                }   
            }   
            return false;
        }
        private void CloseActiveChild(Type t)
        {
            for(int i=0;i<this.MdiChildren.Length;i++)
            {
                if(t.IsInstanceOfType(this.MdiChildren[i]))
                {
                    this.MdiChildren[i].Close();
                }
            }
        }

Thanks NeroToxic! You saved me another day on a project I didn't want to do anyway but when the daughter smiles & says please how can you say no. Very Helpful!

This will open multiple forms of the same class, keeping track of where the last one was closed and opening the new ones there plus an offset.

class mychildforms
{
   public in x,y;
   public string name;
}

on your MDI parent

List<mychildforms> childlist = new List<mychildforms>();

on your close event handler methods

mychildforms mcf;
//need to overrid and maybe overload indexof
if (MDIParent.childlist.IndexOf(this.name) >=0)
 {
   mcf = MDIParent.childlist[MDIParent.childlist.IndexOf(this.name)]
   mcf.x = this.x;
   mcf.y = this.y;
 }
 else
 {
   mcf = new mychildforms();
   mcf.name = this.name;
   mcf.x = this.x;
   mcf.y = this.y;
   MDIParent.childlist.Add(mcf);
 }

on the shown (maybe handlecreated) event handler method

//form default x,y = 0,0
mychildforms mcf;
//need to overrid and maybe overload indexof
if (MDIParent.childlist.IndexOf(this.name) >=0)
 {
   mcf = MDIParent.childlist[MDIParent.childlist.IndexOf(this.name)]
   this.x = mcf.x + xoffset;//or simply the value of x
   this.y = mcf.y + yoffset;//or simply the value of y
 }

its 2AM so the indexof probably needs something but you get the gist.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.