Build a six-cell control array
Create one repeated interface, write one shared Change handler, and test lookup, visibility and missing-member recovery.
Step 1Choose a finished solution or a blank rebuild#
Open the extracted ControlArrayBoard.mcproj in a writable practice folder. The download already contains the complete grid: inspect it, but do not run Create Control Array on top of it. To rebuild from scratch, create a Desktop App, keep one startup Form named frmMain, and add the layout before pasting the code. This lesson needs McBasic™ 0.5.822 or a later compatible build.
Step 2Create the grid and the supporting controls#
Set the Form itself to these values:
| Property | Value |
|---|---|
Caption | Control Array Board |
Width | 580 |
Height | 300 |
MinWidth | 580 |
MinHeight | 300 |
For a blank rebuild, add one TextBox named txtCell with no Index yet. Set Left 24, Top 24, Width 64, Height 36, Text empty, MaxLength 1, Alignment Center and TabIndex 0. Keep Left/Top anchors. Do not paste indexed BASIC code before creating the array.
| Create Control Array field | Value |
|---|---|
| Columns | 3 |
| Rows | 2 |
| Spacing | 12 |
| Group every | 0 |
| Group spacing | 0 |
| Start Index | 0 |
Select the template, choose Design → Create Control Array… and enter the values above. Create produces indexes 0–2 on the first row and 3–5 on the second. Their Left values are 24, 100 and 176; Top is 24 or 72. Give each member AccessibleName Cell 0 through Cell 5.
Add these ordinary, non-array controls directly to the Form. Keep Index empty. The Label uses WordWrap True; keep left/top anchors on the buttons and left/top/right on the Label.
| Type / Name | Left, Top | Width × Height | Caption | TabIndex |
|---|---|---|---|---|
Label / lblStatus | 24, 126 | 520 × 60 | Ready | default |
CommandButton / cmdClear | 24, 212 | 120 × 32 | Clear | 6 |
CommandButton / cmdToggle | 156, 212 | 120 × 32 | Hide / show 5 | 7 |
CommandButton / cmdInspect | 288, 212 | 120 × 32 | Find cell 4 | 8 |
CommandButton / cmdMissing | 420, 212 | 120 × 32 | Probe missing | 9 |
Step 3Connect six members to one procedure#
Bind Change on every txtCell member to the same txtCell_Change procedure. Its first argument identifies the member, so do not create txtCell0_Change and txtCell1_Change. Bind each button Click to its corresponding procedure. Form_Load is the Form lifecycle procedure.
| Owner | Event | Procedure |
|---|---|---|
| txtCell(0)…txtCell(5) | Change | txtCell_Change(ByVal Index As Integer) |
| cmdClear | Click | cmdClear_Click() |
| cmdToggle | Click | cmdToggle_Click() |
| cmdInspect | Click | cmdInspect_Click() |
| cmdMissing | Click | cmdMissing_Click() |
| frmMain | Load | Form_Load() |
Step 4Enter the complete Form code#
Replace frmMain.bas with this entire file. ClearCells sets mLoading before changing Text because programmatic edits also raise Change. UpdateStatus iterates existing members and avoids assuming that every number between the bounds exists. cmdInspect demonstrates typed references; cmdMissing catches a deliberately absent member.
Option Explicit
Private mLoading As Boolean
Private Sub Form_Load()
ClearCells
End Sub
Private Sub ClearCells()
Dim cell As TextBox
mLoading = True
For Each cell In txtCell
cell.Text = ""
cell.Visible = True
Next
mLoading = False
UpdateStatus
End Sub
Private Sub UpdateStatus()
Dim cell As TextBox
Dim filled As Long
For Each cell In txtCell
If Len(cell.Text) > 0 Then filled = filled + 1
Next
lblStatus.Caption = filled & " of " & txtCell.Count & " cells filled; indexes " & txtCell.LBound & " to " & txtCell.UBound
End Sub
Private Sub txtCell_Change(ByVal Index As Integer)
If mLoading Then Exit Sub
UpdateStatus
End Sub
Private Sub cmdClear_Click()
ClearCells
End Sub
Private Sub cmdToggle_Click()
txtCell(5).Visible = Not txtCell(5).Visible
UpdateStatus
End Sub
Private Sub cmdInspect_Click()
Dim found As Control
Dim field As TextBox
Dim references(1) As TextBox
Set references(0) = txtCell(0)
Set references(1) = txtCell(5)
Set found = Me.Controls("txtCell", 4)
If TypeOf found Is TextBox Then
Set field = found
lblStatus.Caption = "Found " & field.Name & "(" & field.Index & "); " & Me.Controls.Count & " controls; last reference " & references(1).Index
End If
End Sub
Private Sub cmdMissing_Click()
Dim missing As TextBox
Try
Set missing = txtCell(99)
Catch
lblStatus.Caption = "Missing member: error " & Err.Number
End Try
End SubStep 5Check the layout contract and save state#
This project has no external resources or dependencies. The full layout below is the downloadable solution, useful for checking names, Index values and event bindings. Save with Command–S and confirm Saved at plus the removal of Edited; a save failure leaves the unsaved state visible.
Complete frmMain.form.json
{
"schemaVersion": 1,
"formId": "main",
"properties": {
"Caption": "Control Array Board",
"Width": 580,
"Height": 300,
"MinWidth": 580,
"MinHeight": 300
},
"layout": {
"mode": "Freeform",
"unit": "DIP"
},
"controls": [
{
"id": "cell-0",
"name": "txtCell",
"type": "McBasic.Standard.TextBox",
"properties": {
"Index": 0,
"Left": 24,
"Top": 24,
"Width": 64,
"Height": 36,
"TabIndex": 0,
"Text": "",
"MaxLength": 1,
"Alignment": "Center",
"AccessibleName": "Cell 0"
},
"anchors": [
"Left",
"Top"
],
"events": [
{
"event": "Change",
"handler": "txtCell_Change"
}
]
},
{
"id": "cell-1",
"name": "txtCell",
"type": "McBasic.Standard.TextBox",
"properties": {
"Index": 1,
"Left": 100,
"Top": 24,
"Width": 64,
"Height": 36,
"TabIndex": 1,
"Text": "",
"MaxLength": 1,
"Alignment": "Center",
"AccessibleName": "Cell 1"
},
"anchors": [
"Left",
"Top"
],
"events": [
{
"event": "Change",
"handler": "txtCell_Change"
}
]
},
{
"id": "cell-2",
"name": "txtCell",
"type": "McBasic.Standard.TextBox",
"properties": {
"Index": 2,
"Left": 176,
"Top": 24,
"Width": 64,
"Height": 36,
"TabIndex": 2,
"Text": "",
"MaxLength": 1,
"Alignment": "Center",
"AccessibleName": "Cell 2"
},
"anchors": [
"Left",
"Top"
],
"events": [
{
"event": "Change",
"handler": "txtCell_Change"
}
]
},
{
"id": "cell-3",
"name": "txtCell",
"type": "McBasic.Standard.TextBox",
"properties": {
"Index": 3,
"Left": 24,
"Top": 72,
"Width": 64,
"Height": 36,
"TabIndex": 3,
"Text": "",
"MaxLength": 1,
"Alignment": "Center",
"AccessibleName": "Cell 3"
},
"anchors": [
"Left",
"Top"
],
"events": [
{
"event": "Change",
"handler": "txtCell_Change"
}
]
},
{
"id": "cell-4",
"name": "txtCell",
"type": "McBasic.Standard.TextBox",
"properties": {
"Index": 4,
"Left": 100,
"Top": 72,
"Width": 64,
"Height": 36,
"TabIndex": 4,
"Text": "",
"MaxLength": 1,
"Alignment": "Center",
"AccessibleName": "Cell 4"
},
"anchors": [
"Left",
"Top"
],
"events": [
{
"event": "Change",
"handler": "txtCell_Change"
}
]
},
{
"id": "cell-5",
"name": "txtCell",
"type": "McBasic.Standard.TextBox",
"properties": {
"Index": 5,
"Left": 176,
"Top": 72,
"Width": 64,
"Height": 36,
"TabIndex": 5,
"Text": "",
"MaxLength": 1,
"Alignment": "Center",
"AccessibleName": "Cell 5"
},
"anchors": [
"Left",
"Top"
],
"events": [
{
"event": "Change",
"handler": "txtCell_Change"
}
]
},
{
"id": "status",
"name": "lblStatus",
"type": "McBasic.Standard.Label",
"properties": {
"Left": 24,
"Top": 126,
"Width": 520,
"Height": 60,
"Caption": "Ready",
"WordWrap": true
},
"anchors": [
"Left",
"Top",
"Right"
],
"events": []
},
{
"id": "cmdClear",
"name": "cmdClear",
"type": "McBasic.Standard.CommandButton",
"properties": {
"Left": 24,
"Top": 212,
"Width": 120,
"Height": 32,
"Caption": "Clear",
"TabIndex": 6
},
"anchors": [
"Left",
"Top"
],
"events": [
{
"event": "Click",
"handler": "cmdClear_Click"
}
]
},
{
"id": "cmdToggle",
"name": "cmdToggle",
"type": "McBasic.Standard.CommandButton",
"properties": {
"Left": 156,
"Top": 212,
"Width": 120,
"Height": 32,
"Caption": "Hide / show 5",
"TabIndex": 7
},
"anchors": [
"Left",
"Top"
],
"events": [
{
"event": "Click",
"handler": "cmdToggle_Click"
}
]
},
{
"id": "cmdInspect",
"name": "cmdInspect",
"type": "McBasic.Standard.CommandButton",
"properties": {
"Left": 288,
"Top": 212,
"Width": 120,
"Height": 32,
"Caption": "Find cell 4",
"TabIndex": 8
},
"anchors": [
"Left",
"Top"
],
"events": [
{
"event": "Click",
"handler": "cmdInspect_Click"
}
]
},
{
"id": "cmdMissing",
"name": "cmdMissing",
"type": "McBasic.Standard.CommandButton",
"properties": {
"Left": 420,
"Top": 212,
"Width": 120,
"Height": 32,
"Caption": "Probe missing",
"TabIndex": 9
},
"anchors": [
"Left",
"Top"
],
"events": [
{
"event": "Click",
"handler": "cmdMissing_Click"
}
]
}
],
"components": []
}Step 6Exercise every branch#
Run Check before Run. Then perform these actions in order:
| Action | Expected result |
|---|---|
| Launch | 0 of 6 cells filled; indexes 0 to 5. |
| Enter A in cell 0 and B in cell 4 | 2 of 6 cells filled. |
| Hide / show 5 twice | Cell 5 disappears and returns; Count remains 6. |
| Find cell 4 | Found txtCell(4); 11 controls; last reference 5. |
| Probe missing | Missing member: error 340. The application stays usable. |
| Clear | All cells are empty and visible; count returns to 0 of 6. |
| Close and reopen the project, then Run | The saved layout and handlers still work. |
mcbasic check ControlArrayBoard.mcprojStep 7Test a genuine gap#
Create a Git checkpoint or another practice copy. Delete txtCell(2) in the Designer and run Check. Run and Clear: the shared For Each code still works, Count is 5 and the highest Index remains 5. The existing lookup uses 4 and the visibility button uses 5, so neither refers to the deleted member. Restore the deleted member with Undo and repeat Check. Do not loop from LBound to UBound and assume index 2 still exists.
Continue with array editing and Target rules or the class-array lesson.
20f4bfed6b · Build manifestSources & maintenance
Original web explanation, reviewed against these repository sources. API tables and example files follow the implementation.
docs/manual/05-designing-forms.mddocs/manual/06-writing-mcbasic.mddocs/manual/21-language-reference.mdsrc/McBasic.Workspace/ControlArrayRules.cssrc/McBasic.Runtime.UI/McControlArray.csmacos/McBasicIDE/Sources/ControlArrays.swiftmacos/McBasicIDE/Sources/CreateControlArraySheet.swiftsite/examples/ControlArrayBoard/ControlArrayBoard.mcprojsite/examples/ControlArrayBoard/frmMain.form.jsonsite/examples/ControlArrayBoard/frmMain.bas