This example shows a form which manages its child forms using a keyed collection:
When you click on the Create a Form B button, a new instance of Form B is created and added to the collection. You can use the other two buttons to move the forms right or left.
Define the Collection
The collection to store child forms is defined like this:
Define_Com Class(#Prim_Kcol<#FormB #Std_Num>) Name(#FormBs)
Add Items to the Collection
The code to create a new form B in the collection is contained in the Click event of the Create a Form B button:
Change Field(#LISTCOUNT) To('#FormBs.ItemCount + 1')
Invoke Method(#FormBs<#listcount>.showform)
In the above note that:
Work with the Collection Items
The click events of the two buttons to move the child forms to right and left use two different ways of working with items in a collection.
The click event of the Move all Form Bs Right button invokes a MoveRight method of Form B for all forms in the collection:
Invoke Method(#formBs<>.MoveRight)
To work with all items in the collection specify a blank key for the collection:
#CollectionName<>
The click event of the Move all Form Bs Left uses a For/EndFor loop to iterate through the items in the collection and to move them to the left:
For Each(#Current) In(#FormBs)
Change Field(#NEW_LEFT) To('#Current.Left - 5')
Set Com(#Current) Left(#New_Left)
Endfor
Also see
Multi-Form Applications
Source Code for Collection Example 3
Form A
Function Options(*DIRECT)
Begin_Com Role(*EXTENDS #PRIM_FORM) Caption('Form A') Clientheight(108) Clientwidth(336) Height(135) Layoutmanager(#GDLM_1) Left(286) Top(124) Width(344)
* Using a Keyed Collection (PRIM_KCOL) to handle a multi-form application.
* Define the keyed collection to be used to store the child forms.
* The collection is named #FormBs and it collects #FormBs.
* It is keyed by #Std_Num ie: a packed (7,0) number.
Define_Com Class(#Prim_Kcol<#FormB #Std_Num>) Name(#FormBs)
* Define the form.
* CreateFormBtn will create an instance of FormB
* MoveRightBtn will move all the child FormBs to the right
* MoveLeftBtn will move all the child FormBs to the left
Define_Com Class(#PRIM_PHBN) Name(#CreateFormBtn) Caption('Create a Form B') Displayposition(1) Left(30) Parent(#COM_OWNER) Tabposition(1) Top(29) Width(109)
Define_Com Class(#PRIM_PHBN) Name(#MoveRightBtn) Caption('Move all Form Bs Right') Displayposition(2) Left(139) Parent(#COM_OWNER) Tabposition(2) Top(29) Width(166)
Define_Com Class(#PRIM_PHBN) Name(#MoveLeftBtn) Caption('Move all Form Bs Left') Displayposition(3) Left(139) Parent(#COM_OWNER) Tabposition(3) Top(54) Width(166)
* Grid layout manager to position the buttons
Define_Com Class(#PRIM_GDLM) Name(#GDLM_1)
Define_Com Class(#PRIM_GDLI) Name(#GDLI_1) Manage(#CreateFormBtn) Parent(#GDLM_1)
Define_Com Class(#PRIM_GDLI) Name(#GDLI_2) Left(2) Manage(#MoveRightBtn) Parent(#GDLM_1)
Define_Com Class(#PRIM_GDLI) Name(#GDLI_4) Left(2) Manage(#MoveLeftBtn) Parent(#GDLM_1) Top(2)
* Definition of child form (FormB)
Define_Com Class(#FORMB) Name(#FORMB) Componentversion(1)
* Fields used to position the child forms (FormB)
Define Field(#NEW_TOP) Reffld(#STD_NUM)
Define Field(#NEW_LEFT) Reffld(#STD_NUM)
Evtroutine Handling(#CreateFormBtn.Click)
* Use the keyed collection property ItemCount to get the next slot in the collection
Change Field(#LISTCOUNT) To('#FormBs.ItemCount + 1')
* Show the form. When the form is shown, it is created and added to the collection
Invoke Method(#FormBs<#listcount>.showform)
* Adjust the form's position from the left and top
Change Field(#NEW_LEFT) To('#FORMBS<#listcount>.Left + (#listcount * 30)')
Change Field(#NEW_TOP) To('#FORMBS<#listcount>.top + (#listcount * 30)')
Set Com(#formBs<#listcount>) Left(#NEW_LEFT) Top(#NEW_TOP)
Endroutine
Evtroutine Handling(#MoveRightBtn.Click)
* Invoke the MoveRight method in FormB to move all forms in the collection to the right
Invoke Method(#formBs<>.MoveRight)
Endroutine
Evtroutine Handling(#MoveLeftBtn.Click)
* Use a For/EndFor loop to iterate through all the forms in the collection and to move them to the left
For Each(#Current) In(#FormBs)
Change Field(#NEW_LEFT) To('#Current.Left - 5')
Set Com(#Current) Left(#New_Left)
Endfor
Endroutine
End_Com
Form B
Function Options(*DIRECT)
Begin_Com Role(*EXTENDS #PRIM_FORM) Caption('Form B') Clientheight(103) Clientwidth(180) Formstyle(StayOnTopChild) Height(130) Layoutmanager(#ATLM_1) Left(591) Top(136) Width(188)
* Define the child FormB used by FormA
* Define a label
Define_Com Class(#PRIM_LABL) Name(#LABL_1) Alignment(Center) Caption('Form B ') Displayposition(1) Height(103) Left(0) Parent(#COM_OWNER) Tabposition(1) Tabstop(False) Top(0) Verticalalignment(Center) Width(180)
* Center the label on the form using an attachment layout
Define_Com Class(#PRIM_ATLM) Name(#ATLM_1)
Define_Com Class(#PRIM_ATLI) Name(#ATLI_1) Attachment(Center) Manage(#LABL_1) Parent(#ATLM_1)
* Define a field to position the form
Define Field(#NEW_RIGHT) Reffld(#STD_NUM)
* Method to move the form to the right by incrementing the value of its Left property
Mthroutine Name(MoveRight) Help('This method moves the form to the right.')
Change Field(#NEW_RIGHT) To('#COM_OWNER.LEFT + 5')
Set Com(#com_owner) Left(#NEW_RIGHT)
Endroutine
End_Com
When you create a new form and specify an ancestor for it, the inheriting form will look and behave exactly like its ancestor form.