Results 1 to 18 of 18

Thread: [RESOLVED] Which child (of MDI form) is where?

  1. #1

    Thread Starter
    Addicted Member
    Join Date
    Sep 2009
    Posts
    190

    Resolved [RESOLVED] Which child (of MDI form) is where?

    Hello. In my program I have MDI form with 4 MDI child forms. They arraranges differently with using the program. I know which is Top form by using Me.activeForm.
    Is there a way to determine exact order of all child forms (from MDI parent) because I would like to save this order at exit so program can load it later same ordered?

  2. #2
    Lively Member Raiser's Avatar
    Join Date
    Oct 2009
    Location
    Tamilnadu,India.
    Posts
    68

    Re: Which child (of MDI form) is where?

    I think this code will give you the active child forms of a MDI form..

    Code:
    Dim frm As Form
    For Each frm In Forms
    If Not TypeOf frm Is MDIForm Then
        If frm.MDIChild Then
               'Yourcode
        End If
    End If
    Next
    Jai Ho... [ May Victory Be Yours]

  3. #3

    Thread Starter
    Addicted Member
    Join Date
    Sep 2009
    Posts
    190

    Re: Which child (of MDI form) is where?

    Thank you Raiser for your code on determining if form is Mdi child or not but this is not question. Question is ORDER (in mean of "deep") of child forms.
    I need to determine which is first, second, third and top form from MDI parent. Is there a way for this?

  4. #4
    Lively Member Raiser's Avatar
    Join Date
    Oct 2009
    Location
    Tamilnadu,India.
    Posts
    68

    Re: Which child (of MDI form) is where?

    Sorry nime.. I don't know how to do this... Let us wait.. Some one could help you..
    Jai Ho... [ May Victory Be Yours]

  5. #5
    Frenzied Member Jim Davis's Avatar
    Join Date
    Mar 2001
    Location
    Mars base one Username: Jim Davis Password: yCrm33
    Posts
    1,284

    Re: Which child (of MDI form) is where?

    Yep i just put this thing together... finally it works.

    Drop this into the mdiform's code
    Code:
    Option Explicit
    Private Declare Function GetWindow Lib "user32" (ByVal hWnd As Long, ByVal wCmd As Long) As Long
    Private Const GW_CHILD = &H5
    Private Const GW_HWNDPREV = &H3
    Private Const GW_HWNDNEXT = &H2
    Private Const GW_HWNDLAST = &H1
    Private Const GW_HWNDFIRST = &H0
    
    Public Function ListFormZOrder(Optional bReverseOrder As Boolean) As Form()
      Dim lhWnd As Long, lhWnd2 As Long
      Dim fChilds() As Form, frm As Form, i As Long, j As Long
      ReDim fChilds(0)
      
      'lets get the child of the mdi
      lhWnd = GetWindow(Me.hWnd, GW_CHILD)
      If lhWnd = 0 Then ListFormZOrder = fChilds: Exit Function
      'actually the child's child is the actual first mdichild form. meh.
      lhWnd = GetWindow(lhWnd, GW_CHILD)
      If lhWnd = 0 Then ListFormZOrder = fChilds: Exit Function
      
      'lets select the first /or last window.
      lhWnd = GetWindow(lhWnd, IIf(bReverseOrder, GW_HWNDLAST, GW_HWNDFIRST))
      If lhWnd = 0 Then ListFormZOrder = fChilds: Exit Function
      
      For Each frm In Forms
        If Not TypeOf frm Is MDIForm Then
          If frm.MDIChild Then
            If lhWnd = frm.hWnd Then
              Set fChilds(0) = frm
              lhWnd2 = GetWindow(lhWnd, IIf(bReverseOrder, GW_HWNDPREV, GW_HWNDNEXT))
              If lhWnd2 = 0 Then ListFormZOrder = fChilds: Exit Function
            Else
              i = UBound(fChilds) + 1
              ReDim Preserve fChilds(i)
              Set fChilds(i) = frm
            End If
          End If
        End If
      Next
    
      For j = 1 To UBound(fChilds) - 1
        For i = j To UBound(fChilds)
          If fChilds(i).hWnd = lhWnd2 Then
            Set frm = fChilds(j)
            Set fChilds(j) = fChilds(i)
            Set fChilds(i) = frm
            Exit For
          End If
        Next i
        lhWnd2 = GetWindow(lhWnd2, IIf(bReverseOrder, GW_HWNDPREV, GW_HWNDNEXT))
        If lhWnd2 = 0 Then
          ListFormZOrder = fChilds
          Exit Function
        End If
      Next j
      
      ListFormZOrder = fChilds
    
    End Function
    And then this one you can use to get the form list in and Ascending or Descending order...

    Code:
    Private Sub Command1_Click()
    Dim FormOrder() As Form, i As Long
    
      FormOrder = MDIForm1.ListFormZOrder(False)
      For i = 0 To UBound(FormOrder)
        Debug.Print FormOrder(i).Caption
      Next i
    
    End Sub
    Probably there is an easy way to do this. But i dont know what would be that.
    Last edited by Jim Davis; Oct 24th, 2009 at 03:10 AM. Reason: tiny bugfix, debug text removed

  6. #6
    Super Moderator Siddharth Rout's Avatar
    Join Date
    Feb 2005
    Location
    Mumbai, India
    Posts
    11,998

    Re: Which child (of MDI form) is where?

    Is there a way to determine exact order of all child forms (from MDI parent) because I would like to save this order at exit so program can load it later same ordered?
    One way I can think of is to cascade all child forms by calling it from the parent form and then close it one by one and at the same time save the settings in an ini file... to cascade you can do the following

    vb Code:
    1. Private Sub a_Click()
    2.     Form3.Show
    3. End Sub
    4. Private Sub b_Click()
    5.     Form2.Show
    6. End Sub
    7. Private Sub c_Click()
    8.     Form1.Show
    9. End Sub
    10.  
    11. Private Sub d_Click()
    12.     Me.Arrange vbCascade
    13. End Sub

    Hope this helps...
    A good exercise for the Heart is to bend down and help another up...
    Please Mark your Thread "Resolved", if the query is solved

    Microsoft MVP: 2011 - 2015 IMP Links : Acceptable Use Policy, FAQ
    MyGear:
    OMEN by HP - 15-ce073tx with Win10+Office 2013. || Mac Book Pro (10.6.8) with Office 2011

  7. #7
    Frenzied Member Jim Davis's Avatar
    Join Date
    Mar 2001
    Location
    Mars base one Username: Jim Davis Password: yCrm33
    Posts
    1,284

    Re: Which child (of MDI form) is where?

    @koolsid: i dont see the reason of the cascadings, since the windows already have the zorder. cascading just reset their size and positions.

  8. #8
    Super Moderator Siddharth Rout's Avatar
    Join Date
    Feb 2005
    Location
    Mumbai, India
    Posts
    11,998

    Re: Which child (of MDI form) is where?

    Sorry I haven't checked your solution yet. I was testing my code when you posted and I didn't refresh the window before posting so I missed your code

    Yes, what you say is correct. Now imagine this worst scenario. The user places all the MDI Child forms in awkward corners of the screen. What the code will do before user closes the application, is to cascade the forms and save their positions, order etc into an ini file so that when the user next opens the application, he will get his order back but of course the forms will be cascaded and neatly arranged...
    A good exercise for the Heart is to bend down and help another up...
    Please Mark your Thread "Resolved", if the query is solved

    Microsoft MVP: 2011 - 2015 IMP Links : Acceptable Use Policy, FAQ
    MyGear:
    OMEN by HP - 15-ce073tx with Win10+Office 2013. || Mac Book Pro (10.6.8) with Office 2011

  9. #9
    Frenzied Member Jim Davis's Avatar
    Join Date
    Mar 2001
    Location
    Mars base one Username: Jim Davis Password: yCrm33
    Posts
    1,284

    Re: Which child (of MDI form) is where?

    But i'm still not sure how the code will help to save the actual zorder, since the zorder is ignored when you close the forms. The form collection have its own order, that is differs from the zorder. Unfortunately it seems like this internal order will be used to closing the forms one by one (even if you arranged them).

    just place a debug.print into each child form's unload event, and see it for yourself, it doesnt matters a window is the topmost, or the bottom most; the order of the opens (or arrivals) will be used to closing the windows, not the z orders

  10. #10
    Former Admin/Moderator MartinLiss's Avatar
    Join Date
    Sep 1999
    Location
    San Jose, CA
    Posts
    33,172

    Re: Which child (of MDI form) is where?

    Here's a pretty easy way to do it.

    Put the following in a code module:
    Code:
    Option Explicit
    
    Public colForms As New Collection
    
    Public Sub AddToCollection(frm As String)
    On Error Resume Next
    colForms.Remove frm
    
    If colForms.Count = 0 Then
        colForms.Add frm, frm
    Else
        colForms.Add frm, frm, 1
    End If
    
    End Sub
    Then in each mdi child form do the following
    Code:
    Private Sub Form_GotFocus()
    
    AddToCollection Me.Name
    
    End Sub
    
    Private Sub Form_Load()
    
    AddToCollection Me.Name
    
    End Sub
    And finally in the MDIForm do this:
    Code:
    Private Sub MDIForm_Load()
    
    Dim strForms() As String
    Dim strDummy As String
    Dim lngIndex As Long
    
    strDummy = GetSetting(App.EXEName, "Settings", "mdi child order", "none")
    
    If strDummy <> "none" Then
        strForms = Split(strDummy, ",")
        For lngIndex = UBound(strForms) To 0 Step -1
            Select Case strForms(lngIndex)
                Case "Form1" 'Change these to the names of your MDI Child forms
                    Form1.Show
                Case "Form2"
                    Form2.Show
                Case "Form3"
                    Form3.Show
                Case "Form4"
                    Form4.Show
            End Select
        Next
    End If
    
    End Sub
    
    
    Private Sub MDIForm_Unload(Cancel As Integer)
    
    Dim lngIndex As Long
    Dim strForms As String
    
    For lngIndex = 1 To colForms.Count
        If lngIndex = 1 Then
            strForms = strForms & colForms(lngIndex)
        Else
            strForms = strForms & "," & colForms(lngIndex)
        End If
    Next
    
    SaveSetting App.EXEName, "Settings", "mdi child order", strForms
    
    End Sub

  11. #11
    Former Admin/Moderator MartinLiss's Avatar
    Join Date
    Sep 1999
    Location
    San Jose, CA
    Posts
    33,172

    Re: Which child (of MDI form) is where?

    An improvement. Replace the above MDIForm_Load with this:

    Code:
    Private Sub MDIForm_Load()
    
    Dim strForms() As String
    Dim strDummy As String
    Dim lngIndex As Long
    Dim frm As Form
    
    strDummy = GetSetting(App.EXEName, "Settings", "mdi child order", "none")
    
    If strDummy <> "none" Then
        strForms = Split(strDummy, ",")
        For lngIndex = UBound(strForms) To 0 Step -1
            Set frm = VB.Forms.Add(strForms(lngIndex))
            frm.Show
        Next
    End If
    
    End Sub

  12. #12
    Frenzied Member Jim Davis's Avatar
    Join Date
    Mar 2001
    Location
    Mars base one Username: Jim Davis Password: yCrm33
    Posts
    1,284

    Re: Which child (of MDI form) is where?

    @MartinLiss: yeah, that seems to me like the easy way to do it! i will test it now.

  13. #13
    PowerPoster RhinoBull's Avatar
    Join Date
    Mar 2004
    Location
    New Amsterdam
    Posts
    24,135

    Re: Which child (of MDI form) is where?

    I usually do something silmilar to what Marty did - I would use array, populate child form tag property with some public counter value (it gets incremented for every new child).
    Very simple and also bulletproof technic in case you need to maintain forms order.

  14. #14

    Thread Starter
    Addicted Member
    Join Date
    Sep 2009
    Posts
    190

    Re: Which child (of MDI form) is where?

    I'm wery sorry for late respond but my computer's FAT crashes during repartition as first step for installing one new operating system from one known software manufacurer. Back up data costs almost two days and my first expressions of those new software is not good.
    Very thanks for all which was trying to help me on this thema.
    Martin Liss, I already use collection of forms here and one class what allows me to to manage children events through mdi parent so parent can know what happens with children in mean of click, close, move and few more events.
    Jim Davis give one excelent example which works wery good.
    With this I save my forms like this:

    Code:
        Dim FormOrder() As Form, i As Long
        Dim ff As Integer
            ff = FreeFile
            Open tmpDir + "AKTf.tmp" For Output As #ff
            FormOrder = Me.ListFormZOrder(True)
            For i = 0 To UBound(FormOrder)
             If FormOrder(i).Name > "" Then
                Write #ff, FormOrder(i).Name
                End If
            End If
          Next i
          Close #ff
          Me.Arrange vbCascade
    Koolsid, I use vbCascade for arranging method too. This programm have purpose to rotate forms when you click on some and then reorder them in cascade. I would like to make this flexible because I planed to use this in further programms.

    But after Jim Davises solution I dont know how to load this forms back. I can't use for each frm in forms because in start forms are not loaded yet. I have now saved names of forms and I would like to load forms regarding those names. I try this:

    Code:
        Dim myFormName() As String
        ReDim myFormName(4)
    
    ' some default order
    
        myFormName(0) = "mOts"
        myFormName(1) = "mMed"
        myFormName(2) = "mPre"
        myFormName(3) = "mOtp"
         
    ' if saved order exist repopulate array with concrete order
    
        Dim x As Integer, MemFormName As String
         If FExist(tmpDir + "AKTf.tmp") Then
            ff = FreeFile
                   Open tmpDir + "AKTf.tmp" For Input As #ff
                   Do While Not EOF(ff)
                      Input #ff, MemFormName
                      myFormName(x) = MemFormName
                      x = x + 1
                   Loop
                   Close #ff
               End If
    
     ' here I have right order but I can't reference formy through its names?
    
        Dim frm As Form, t As Integer
        For t = 0 To UBound(myFormName)
        Set frm = myFormName(t)   ' Here commes ERROR 'type mismatch'
    
        ' famous Raises part of code
    If Not TypeOf frm Is MDIForm Then
        If frm.MDIChild Then
               'Yourcode like FormWithName_MyFormName(t).Show
                Debug.Print frm.Name ' for see what happens
        
        End If
        Next t
    I need additional help for loading forms yet so please advice me to finish this part of programm. Your advices helps me already very much and I am very grateful. As you can see I still fighting with VB6 basics.

  15. #15

  16. #16

    Thread Starter
    Addicted Member
    Join Date
    Sep 2009
    Posts
    190

    Re: Which child (of MDI form) is where?

    Yes Martin, your code works. Now I taked a part from it and finally finishes with this problem which bothers me some time. I loaded formy "by name" like this:

    Code:
        Dim frm As Form, t As Integer
        For t = 0 To UBound(myFormName) - 1
        Set frm = Forms.Add(myFormName(t))
     If Not TypeOf frm Is MDIForm Then
                If frm.MDIChild Then Debug.Print frm.Name
                       End If
        Next t
    Thanks all for help once more!

  17. #17
    Former Admin/Moderator MartinLiss's Avatar
    Join Date
    Sep 1999
    Location
    San Jose, CA
    Posts
    33,172

    Re: [RESOLVED] Which child (of MDI form) is where?

    Okay if you now have your answer, you can help us by marking the thread as resolved. If you have JavaScript enabled you can do that by selecting the Mark Thread Resolved item from the Thread Tools menu. Otherwise please insert "[Resolved]" at the start of the Subject and select the green checkmark from the Post Icons.

  18. #18
    Frenzied Member Jim Davis's Avatar
    Join Date
    Mar 2001
    Location
    Mars base one Username: Jim Davis Password: yCrm33
    Posts
    1,284

    Re: [RESOLVED] Which child (of MDI form) is where?

    But after Jim Davises solution I dont know how to load this forms back. I can't use for each frm in forms because in start forms are not loaded yet.
    Yes i didn't provided Save or Load features because you didn't asked for it. You just needed the form zorder, i gave you the example that i put together. If you ever need a working save/load feature, you don't have to do much but by modifying Marty's code you just have to concatenate the string array (but not the collection's element), and save it. Thats all. The loading part is fine.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width