Manage independent Form instances
Create, show, hide and unload windows deliberately.
New creates a distinct instance. Show presents it; Hide removes it from view without necessarily discarding its state; Unload ends the Form lifecycle. QueryUnload can cancel closure. Use the sample’s lifecycle feedback to observe the order instead of assuming every Show creates a new window.
Step 1Prepare a safe practice project#
Extract the archive into a new writable folder, separate from your own application. Open MultiForms.mcproj in McBasic™. Keep every declared source, layout, resource and migration file together.
To reconstruct it yourself, create a DesktopApp project and add the files declared below. In the complete project, follow these steps as a guided rebuild: replace each named source file once and Check after all its procedures are present.
Exact project configuration
{
"schemaVersion": 1,
"projectId": "357c7963-827f-484a-b5a8-3714b1d6ea04",
"name": "MultiForms",
"kind": "DesktopApp",
"language": {
"dialect": "McBasic1",
"requireExplicit": true,
"compare": "Binary",
"defaultArrayBase": 0
},
"application": {
"bundleIdentifier": "com.mcbasic.samples.multiforms",
"version": "0.1.0",
"buildNumber": "1",
"startupFormId": "form-main",
"shutdownMode": "OnStartupFormClosed"
},
"forms": [
{
"id": "form-main",
"typeName": "frmMain",
"layout": "Forms/frmMain.form.json",
"code": "Forms/frmMain.bas"
},
{
"id": "form-details",
"typeName": "frmDetails",
"layout": "Forms/frmDetails.form.json",
"code": "Forms/frmDetails.bas"
}
],
"modules": [],
"classes": [],
"tests": [],
"references": [],
"resources": [],
"targets": [
"osx-arm64"
],
"capabilities": []
}Step 2Build the Form and set its properties#
frmMain
Select the Form first and set its properties. Add containers before their children. These are initial Designer values, not statements to paste into a procedure.
| Form property | Value |
|---|---|
Caption | "MultiForms — independent windows" |
Width | 560 |
Height | 320 |
MinWidth | 520 |
MinHeight | 280 |
| Type | Name | Parent |
|---|---|---|
| Label | lblIntro | Form |
| CommandButton | cmdAlpha | Form |
| CommandButton | cmdBeta | Form |
| Label | lblStatus | Form |
| CommandButton | cmdClose | Form |
lblIntro · exact Inspector values
| Property | Value |
|---|---|
Left | 24 |
Top | 24 |
Width | 500 |
Height | 44 |
Caption | "Open two independent Forms. Each window has its own lifecycle." |
| Anchor edges | Left, Top |
cmdAlpha · exact Inspector values
| Property | Value |
|---|---|
Left | 24 |
Top | 92 |
Width | 160 |
Height | 38 |
Caption | "Open Alpha" |
TabIndex | 0 |
| Anchor edges | Left, Top |
cmdBeta · exact Inspector values
| Property | Value |
|---|---|
Left | 200 |
Top | 92 |
Width | 160 |
Height | 38 |
Caption | "Open Beta" |
TabIndex | 1 |
| Anchor edges | Left, Top |
lblStatus · exact Inspector values
| Property | Value |
|---|---|
Left | 24 |
Top | 158 |
Width | 500 |
Height | 52 |
Caption | "Ready. No secondary Forms are open." |
| Anchor edges | Left, Top |
cmdClose · exact Inspector values
| Property | Value |
|---|---|
Left | 24 |
Top | 236 |
Width | 160 |
Height | 38 |
Caption | "Close main Form" |
TabIndex | 2 |
| Anchor edges | Left, Top |
frmDetails
Select the Form first and set its properties. Add containers before their children. These are initial Designer values, not statements to paste into a procedure.
| Form property | Value |
|---|---|
Caption | "Details window" |
Width | 360 |
Height | 220 |
MinWidth | 320 |
MinHeight | 190 |
| Type | Name | Parent |
|---|---|---|
| Label | lblName | Form |
| CommandButton | cmdHide | Form |
| CommandButton | cmdUnload | Form |
lblName · exact Inspector values
| Property | Value |
|---|---|
Left | 24 |
Top | 24 |
Width | 300 |
Height | 44 |
Caption | "Details window" |
| Anchor edges | Left, Top |
cmdHide · exact Inspector values
| Property | Value |
|---|---|
Left | 24 |
Top | 96 |
Width | 140 |
Height | 36 |
Caption | "Hide window" |
TabIndex | 0 |
| Anchor edges | Left, Top |
cmdUnload · exact Inspector values
| Property | Value |
|---|---|
Left | 176 |
Top | 96 |
Width | 140 |
Height | 36 |
Caption | "Unload window" |
TabIndex | 1 |
| Anchor edges | Left, Top |
Step 3Connect the events explicitly#
frmMain
| Object | Event | Procedure | Parameters |
|---|---|---|---|
cmdAlpha | Click | cmdAlpha_Click | Click() |
cmdBeta | Click | cmdBeta_Click | Click() |
cmdClose | Click | cmdClose_Click | Click() |
| Form | Shown | Form_Shown | () |
frmDetails
| Object | Event | Procedure | Parameters |
|---|---|---|---|
cmdHide | Click | cmdHide_Click | Click() |
cmdUnload | Click | cmdUnload_Click | Click() |
| Form | Initialize | Form_Initialize | () |
| Form | Load | Form_Load | () |
| Form | Shown | Form_Shown | () |
| Form | QueryUnload | Form_QueryUnload | (ByRef Cancel As Integer, ByVal UnloadMode As Integer) |
| Form | Unload | Form_Unload | () |
Step 4Enter the complete behavior#
Open the named source file. Enter declarations first, then every procedure. Expand a procedure for its full body, or copy the complete file. Helpers are required: do not stop after entering the first Click handler.
Forms/frmMain.bas
Enter these declarations at file scope, before the procedures.
Option ExplicitPrivate Sub Form_Shown()
Initialize state before enabling dependent actions. Keep the shared declarations and startup dependencies with this procedure.
Private Sub Form_Shown()
Dim alpha As frmDetails
Dim beta As frmDetails
Set alpha = New frmDetails
Set beta = New frmDetails
alpha.DisplayName = "Alpha"
beta.DisplayName = "Beta"
alpha.Show
beta.Show
lblStatus.Caption = "Alpha and Beta are independent windows."
End SubPrivate Sub cmdAlpha_Click()
Enter the complete action, including its input checks and calls to helper procedures.
Private Sub cmdAlpha_Click()
Dim alpha As frmDetails
Set alpha = New frmDetails
alpha.DisplayName = "Alpha"
alpha.Show
lblStatus.Caption = "Alpha is an independent window."
End SubPrivate Sub cmdBeta_Click()
Enter the complete action, including its input checks and calls to helper procedures.
Private Sub cmdBeta_Click()
Dim beta As frmDetails
Set beta = New frmDetails
beta.DisplayName = "Beta"
beta.Show
lblStatus.Caption = "Beta is an independent window."
End SubPrivate Sub cmdClose_Click()
Enter the complete action, including its input checks and calls to helper procedures.
Private Sub cmdClose_Click()
Unload Me
End SubCopy the complete Forms/frmMain.bas file
Replace the file once; do not append duplicate procedures.
Option Explicit
Private Sub Form_Shown()
Dim alpha As frmDetails
Dim beta As frmDetails
Set alpha = New frmDetails
Set beta = New frmDetails
alpha.DisplayName = "Alpha"
beta.DisplayName = "Beta"
alpha.Show
beta.Show
lblStatus.Caption = "Alpha and Beta are independent windows."
End Sub
Private Sub cmdAlpha_Click()
Dim alpha As frmDetails
Set alpha = New frmDetails
alpha.DisplayName = "Alpha"
alpha.Show
lblStatus.Caption = "Alpha is an independent window."
End Sub
Private Sub cmdBeta_Click()
Dim beta As frmDetails
Set beta = New frmDetails
beta.DisplayName = "Beta"
beta.Show
lblStatus.Caption = "Beta is an independent window."
End Sub
Private Sub cmdClose_Click()
Unload Me
End SubForms/frmDetails.bas
Enter these declarations at file scope, before the procedures.
Option Explicit
Public DisplayName As StringPrivate Sub Form_Initialize()
Initialize state before enabling dependent actions. Keep the shared declarations and startup dependencies with this procedure.
Private Sub Form_Initialize()
Debug.Print "initialize:" & DisplayName
End SubPrivate Sub Form_Load()
Initialize state before enabling dependent actions. Keep the shared declarations and startup dependencies with this procedure.
Private Sub Form_Load()
Debug.Print "load:" & DisplayName
End SubPrivate Sub Form_Shown()
Initialize state before enabling dependent actions. Keep the shared declarations and startup dependencies with this procedure.
Private Sub Form_Shown()
lblName.Caption = "Details window: " & DisplayName
Debug.Print "shown:" & DisplayName
End SubPrivate Sub cmdHide_Click()
Enter the complete action, including its input checks and calls to helper procedures.
Private Sub cmdHide_Click()
Me.Hide
Debug.Print "hidden:" & DisplayName
End SubPrivate Sub cmdUnload_Click()
Enter the complete action, including its input checks and calls to helper procedures.
Private Sub cmdUnload_Click()
Unload Me
End SubPrivate Sub Form_QueryUnload(ByRef Cancel As Integer, ByVal UnloadMode As Integer)
This is the lifetime boundary. Preserve the cancellation signature where present and release resources owned by this Form.
Private Sub Form_QueryUnload(ByRef Cancel As Integer, ByVal UnloadMode As Integer)
Debug.Print "query:" & DisplayName & ":" & UnloadMode
End SubPrivate Sub Form_Unload()
This is the lifetime boundary. Preserve the cancellation signature where present and release resources owned by this Form.
Private Sub Form_Unload()
Debug.Print "unload:" & DisplayName
End SubCopy the complete Forms/frmDetails.bas file
Replace the file once; do not append duplicate procedures.
Option Explicit
Public DisplayName As String
Private Sub Form_Initialize()
Debug.Print "initialize:" & DisplayName
End Sub
Private Sub Form_Load()
Debug.Print "load:" & DisplayName
End Sub
Private Sub Form_Shown()
lblName.Caption = "Details window: " & DisplayName
Debug.Print "shown:" & DisplayName
End Sub
Private Sub cmdHide_Click()
Me.Hide
Debug.Print "hidden:" & DisplayName
End Sub
Private Sub cmdUnload_Click()
Unload Me
End Sub
Private Sub Form_QueryUnload(ByRef Cancel As Integer, ByVal UnloadMode As Integer)
Debug.Print "query:" & DisplayName & ":" & UnloadMode
End Sub
Private Sub Form_Unload()
Debug.Print "unload:" & DisplayName
End SubStep 5Keep resources and storage reproducible#
No external resource or migration files are declared. Any inline migration, seed data or local JSON is present in the code above. Runtime application data and private preferences are not included in the archive.
Step 6Check, run and test the result#
Save all files and run Check. Resolve diagnostics before Run. Developer CLI users can work from the extracted folder:
mcbasic check MultiForms.mcproj
mcbasic run MultiForms.mcprojAcceptance checklist
- Open Alpha and Beta and compare their state.
- Hide an instance and show it again.
- Unload an instance and reopen it.
- Exercise the close veto and inspect lifecycle messages.
Step 7Make one change and repeat the tests#
Pass a public property to each new Form before showing it.
Save a working Git checkpoint first. Change one behavior, Check again and repeat the acceptance checklist. Compare with the downloaded solution if a regression appears.
20f4bfed6b · Build manifest