From e4d6aede87e7bfa41b8963c10510843fa70fafef Mon Sep 17 00:00:00 2001 From: Kuba Sunderland-Ober Date: Sat, 14 Feb 2026 21:08:37 +0100 Subject: [PATCH 1/2] Move tutorials to their own heading. --- docs/CustomControls/index.md | 7 ------- .../CustomControls/Defining a CustomControl.md | 4 +++- .../CustomControls/Images/ccCOMCreatable.png | Bin .../Images/ccClassIdAttribute.png | Bin .../CustomControls/Images/ccClassIdInsert.png | Bin .../Images/ccCustomControlAttribute.png | Bin .../CustomControls/Images/ccEvents.png | Bin .../CustomControls/Images/ccGridButtonImage.png | Bin .../CustomControls/Images/ccICustomControl.png | Bin .../Images/ccMyEnumFieldPropertySheet.png | Bin .../CustomControls/Images/ccMyFieldArray.png | Bin .../CustomControls/Images/ccMyFieldClass.png | Bin .../Images/ccMyFieldCustomProperty.png | Bin .../CustomControls/Images/ccMyFieldJson1a.png | Bin .../Images/ccMyFieldPropertySheet1a.png | Bin .../Images/ccMyFieldPropertySheet1b.png | Bin .../CustomControls/Images/ccSampleProject.png | Bin .../Notes about the form designer.md | 4 +++- .../Painting-drawing to your control.md | 4 +++- .../Property sheet and object serialization.md | 4 +++- .../CustomControls/_Images/ccSampleProject.af | Bin .../CustomControls/index.md} | 13 ++++++++----- .../WebView2/Customize the UserDataFolder.md | 4 +++- .../{ => Tutorials}/WebView2/Getting started.md | 4 +++- .../WebView2/Images/tbWebView2CreateEvent.png | Bin .../WebView2/Images/tbWebView2InAForm.gif | Bin .../WebView2/Images/tbWebView2Properties.png | Bin .../WebView2/Images/tbWebView2References.png | Bin .../WebView2/Images/tbWebView2Sample0.png | Bin .../WebView2/Images/tbWebView2Toolbox.png | Bin docs/{ => Tutorials}/WebView2/Re-entrancy.md | 4 +++- docs/Tutorials/WebView2/index.md | 10 ++++++++++ docs/Tutorials/index.md | 6 ++++++ docs/WebView2/index.md | 8 -------- docs/index.md | 16 +++++----------- 35 files changed, 50 insertions(+), 38 deletions(-) delete mode 100644 docs/CustomControls/index.md rename docs/{ => Tutorials}/CustomControls/Defining a CustomControl.md (97%) rename docs/{ => Tutorials}/CustomControls/Images/ccCOMCreatable.png (100%) rename docs/{ => Tutorials}/CustomControls/Images/ccClassIdAttribute.png (100%) rename docs/{ => Tutorials}/CustomControls/Images/ccClassIdInsert.png (100%) rename docs/{ => Tutorials}/CustomControls/Images/ccCustomControlAttribute.png (100%) rename docs/{ => Tutorials}/CustomControls/Images/ccEvents.png (100%) rename docs/{ => Tutorials}/CustomControls/Images/ccGridButtonImage.png (100%) rename docs/{ => Tutorials}/CustomControls/Images/ccICustomControl.png (100%) rename docs/{ => Tutorials}/CustomControls/Images/ccMyEnumFieldPropertySheet.png (100%) rename docs/{ => Tutorials}/CustomControls/Images/ccMyFieldArray.png (100%) rename docs/{ => Tutorials}/CustomControls/Images/ccMyFieldClass.png (100%) rename docs/{ => Tutorials}/CustomControls/Images/ccMyFieldCustomProperty.png (100%) rename docs/{ => Tutorials}/CustomControls/Images/ccMyFieldJson1a.png (100%) rename docs/{ => Tutorials}/CustomControls/Images/ccMyFieldPropertySheet1a.png (100%) rename docs/{ => Tutorials}/CustomControls/Images/ccMyFieldPropertySheet1b.png (100%) rename docs/{ => Tutorials}/CustomControls/Images/ccSampleProject.png (100%) rename docs/{ => Tutorials}/CustomControls/Notes about the form designer.md (72%) rename docs/{ => Tutorials}/CustomControls/Painting-drawing to your control.md (98%) rename docs/{ => Tutorials}/CustomControls/Property sheet and object serialization.md (97%) rename docs/{ => Tutorials}/CustomControls/_Images/ccSampleProject.af (100%) rename docs/{CustomControls/Introduction.md => Tutorials/CustomControls/index.md} (85%) rename docs/{ => Tutorials}/WebView2/Customize the UserDataFolder.md (92%) rename docs/{ => Tutorials}/WebView2/Getting started.md (94%) rename docs/{ => Tutorials}/WebView2/Images/tbWebView2CreateEvent.png (100%) rename docs/{ => Tutorials}/WebView2/Images/tbWebView2InAForm.gif (100%) rename docs/{ => Tutorials}/WebView2/Images/tbWebView2Properties.png (100%) rename docs/{ => Tutorials}/WebView2/Images/tbWebView2References.png (100%) rename docs/{ => Tutorials}/WebView2/Images/tbWebView2Sample0.png (100%) rename docs/{ => Tutorials}/WebView2/Images/tbWebView2Toolbox.png (100%) rename docs/{ => Tutorials}/WebView2/Re-entrancy.md (96%) create mode 100644 docs/Tutorials/WebView2/index.md create mode 100644 docs/Tutorials/index.md delete mode 100644 docs/WebView2/index.md diff --git a/docs/CustomControls/index.md b/docs/CustomControls/index.md deleted file mode 100644 index b2ed562..0000000 --- a/docs/CustomControls/index.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: CustomControls -nav_order: 3 -permalink: /CustomControls ---- - -# CustomControls \ No newline at end of file diff --git a/docs/CustomControls/Defining a CustomControl.md b/docs/Tutorials/CustomControls/Defining a CustomControl.md similarity index 97% rename from docs/CustomControls/Defining a CustomControl.md rename to docs/Tutorials/CustomControls/Defining a CustomControl.md index d6fefa8..e238574 100644 --- a/docs/CustomControls/Defining a CustomControl.md +++ b/docs/Tutorials/CustomControls/Defining a CustomControl.md @@ -2,7 +2,9 @@ title: Defining a CustomControl parent: CustomControls nav_order: 2 -permalink: /CustomControls/Defining +permalink: /Tutorials/CustomControls/Defining +redirect_from: + - /CustomControls/Defining --- # Defining a CustomControl A CustomControl is simply an ordinary twinBASIC class, with a few extra attributes and requirements. diff --git a/docs/CustomControls/Images/ccCOMCreatable.png b/docs/Tutorials/CustomControls/Images/ccCOMCreatable.png similarity index 100% rename from docs/CustomControls/Images/ccCOMCreatable.png rename to docs/Tutorials/CustomControls/Images/ccCOMCreatable.png diff --git a/docs/CustomControls/Images/ccClassIdAttribute.png b/docs/Tutorials/CustomControls/Images/ccClassIdAttribute.png similarity index 100% rename from docs/CustomControls/Images/ccClassIdAttribute.png rename to docs/Tutorials/CustomControls/Images/ccClassIdAttribute.png diff --git a/docs/CustomControls/Images/ccClassIdInsert.png b/docs/Tutorials/CustomControls/Images/ccClassIdInsert.png similarity index 100% rename from docs/CustomControls/Images/ccClassIdInsert.png rename to docs/Tutorials/CustomControls/Images/ccClassIdInsert.png diff --git a/docs/CustomControls/Images/ccCustomControlAttribute.png b/docs/Tutorials/CustomControls/Images/ccCustomControlAttribute.png similarity index 100% rename from docs/CustomControls/Images/ccCustomControlAttribute.png rename to docs/Tutorials/CustomControls/Images/ccCustomControlAttribute.png diff --git a/docs/CustomControls/Images/ccEvents.png b/docs/Tutorials/CustomControls/Images/ccEvents.png similarity index 100% rename from docs/CustomControls/Images/ccEvents.png rename to docs/Tutorials/CustomControls/Images/ccEvents.png diff --git a/docs/CustomControls/Images/ccGridButtonImage.png b/docs/Tutorials/CustomControls/Images/ccGridButtonImage.png similarity index 100% rename from docs/CustomControls/Images/ccGridButtonImage.png rename to docs/Tutorials/CustomControls/Images/ccGridButtonImage.png diff --git a/docs/CustomControls/Images/ccICustomControl.png b/docs/Tutorials/CustomControls/Images/ccICustomControl.png similarity index 100% rename from docs/CustomControls/Images/ccICustomControl.png rename to docs/Tutorials/CustomControls/Images/ccICustomControl.png diff --git a/docs/CustomControls/Images/ccMyEnumFieldPropertySheet.png b/docs/Tutorials/CustomControls/Images/ccMyEnumFieldPropertySheet.png similarity index 100% rename from docs/CustomControls/Images/ccMyEnumFieldPropertySheet.png rename to docs/Tutorials/CustomControls/Images/ccMyEnumFieldPropertySheet.png diff --git a/docs/CustomControls/Images/ccMyFieldArray.png b/docs/Tutorials/CustomControls/Images/ccMyFieldArray.png similarity index 100% rename from docs/CustomControls/Images/ccMyFieldArray.png rename to docs/Tutorials/CustomControls/Images/ccMyFieldArray.png diff --git a/docs/CustomControls/Images/ccMyFieldClass.png b/docs/Tutorials/CustomControls/Images/ccMyFieldClass.png similarity index 100% rename from docs/CustomControls/Images/ccMyFieldClass.png rename to docs/Tutorials/CustomControls/Images/ccMyFieldClass.png diff --git a/docs/CustomControls/Images/ccMyFieldCustomProperty.png b/docs/Tutorials/CustomControls/Images/ccMyFieldCustomProperty.png similarity index 100% rename from docs/CustomControls/Images/ccMyFieldCustomProperty.png rename to docs/Tutorials/CustomControls/Images/ccMyFieldCustomProperty.png diff --git a/docs/CustomControls/Images/ccMyFieldJson1a.png b/docs/Tutorials/CustomControls/Images/ccMyFieldJson1a.png similarity index 100% rename from docs/CustomControls/Images/ccMyFieldJson1a.png rename to docs/Tutorials/CustomControls/Images/ccMyFieldJson1a.png diff --git a/docs/CustomControls/Images/ccMyFieldPropertySheet1a.png b/docs/Tutorials/CustomControls/Images/ccMyFieldPropertySheet1a.png similarity index 100% rename from docs/CustomControls/Images/ccMyFieldPropertySheet1a.png rename to docs/Tutorials/CustomControls/Images/ccMyFieldPropertySheet1a.png diff --git a/docs/CustomControls/Images/ccMyFieldPropertySheet1b.png b/docs/Tutorials/CustomControls/Images/ccMyFieldPropertySheet1b.png similarity index 100% rename from docs/CustomControls/Images/ccMyFieldPropertySheet1b.png rename to docs/Tutorials/CustomControls/Images/ccMyFieldPropertySheet1b.png diff --git a/docs/CustomControls/Images/ccSampleProject.png b/docs/Tutorials/CustomControls/Images/ccSampleProject.png similarity index 100% rename from docs/CustomControls/Images/ccSampleProject.png rename to docs/Tutorials/CustomControls/Images/ccSampleProject.png diff --git a/docs/CustomControls/Notes about the form designer.md b/docs/Tutorials/CustomControls/Notes about the form designer.md similarity index 72% rename from docs/CustomControls/Notes about the form designer.md rename to docs/Tutorials/CustomControls/Notes about the form designer.md index b1dabbb..2450f9d 100644 --- a/docs/CustomControls/Notes about the form designer.md +++ b/docs/Tutorials/CustomControls/Notes about the form designer.md @@ -2,7 +2,9 @@ title: Notes About the Form Designer parent: CustomControls nav_order: 5 -permalink: /CustomControls/Form Designer +permalink: /Tutorials/CustomControls/Form Designer +redirect_from: + - /CustomControls/Form Designer --- # Notes About the Form Designer diff --git a/docs/CustomControls/Painting-drawing to your control.md b/docs/Tutorials/CustomControls/Painting-drawing to your control.md similarity index 98% rename from docs/CustomControls/Painting-drawing to your control.md rename to docs/Tutorials/CustomControls/Painting-drawing to your control.md index 213168c..0afa6ff 100644 --- a/docs/CustomControls/Painting-drawing to your control.md +++ b/docs/Tutorials/CustomControls/Painting-drawing to your control.md @@ -2,7 +2,9 @@ title: Painting / Drawing to Your Control parent: CustomControls nav_order: 4 -permalink: /CustomControls/Painting +permalink: /Tutorials/CustomControls/Painting +redirect_from: + - /CustomControls/Painting --- # Painting / Drawing to Your Control diff --git a/docs/CustomControls/Property sheet and object serialization.md b/docs/Tutorials/CustomControls/Property sheet and object serialization.md similarity index 97% rename from docs/CustomControls/Property sheet and object serialization.md rename to docs/Tutorials/CustomControls/Property sheet and object serialization.md index c8b791b..5407bbb 100644 --- a/docs/CustomControls/Property sheet and object serialization.md +++ b/docs/Tutorials/CustomControls/Property sheet and object serialization.md @@ -2,7 +2,9 @@ title: Property Sheet and Object Serialization parent: CustomControls nav_order: 3 -permalink: /CustomControls/Properties +permalink: /Tutorials/CustomControls/Properties +redirect_from: + - /CustomControls/Properties --- # Property Sheet and Object Serialization The form designer property sheet will pickup any **_public_** custom properties (fields) that you expose via your CustomControl class. For example, adding a field `Public MyField As Long` will then automatically show up in the control property sheet in the form designer: diff --git a/docs/CustomControls/_Images/ccSampleProject.af b/docs/Tutorials/CustomControls/_Images/ccSampleProject.af similarity index 100% rename from docs/CustomControls/_Images/ccSampleProject.af rename to docs/Tutorials/CustomControls/_Images/ccSampleProject.af diff --git a/docs/CustomControls/Introduction.md b/docs/Tutorials/CustomControls/index.md similarity index 85% rename from docs/CustomControls/Introduction.md rename to docs/Tutorials/CustomControls/index.md index fa1f8dd..6b2e0f5 100644 --- a/docs/CustomControls/Introduction.md +++ b/docs/Tutorials/CustomControls/index.md @@ -1,15 +1,18 @@ --- -title: Introduction -parent: CustomControls -nav_order: 1 -permalink: /CustomControls/Introduction +title: CustomControls +parent: Tutorials +permalink: /Tutorials/CustomControls +redirect_from: + - /CustomControls + - /CustomControls/Introduction --- -### Introduction +# CustomControls twinBASIC now offers experimental support for CustomControls. CustomControls are implemented using the BASIC language, allowing implementers to design controls directly from the twinBASIC environment. A few highlights; + - completely custom drawn controls, with no external or third-party dependencies (tiny footprint) - support 32-bit RGBA for full alpha-transparency - support high-DPI modes (per-monitor), requiring little thought whilst designing new controls diff --git a/docs/WebView2/Customize the UserDataFolder.md b/docs/Tutorials/WebView2/Customize the UserDataFolder.md similarity index 92% rename from docs/WebView2/Customize the UserDataFolder.md rename to docs/Tutorials/WebView2/Customize the UserDataFolder.md index 4c7789e..ed2ccbb 100644 --- a/docs/WebView2/Customize the UserDataFolder.md +++ b/docs/Tutorials/WebView2/Customize the UserDataFolder.md @@ -2,7 +2,9 @@ title: Customize the UserDataFolder parent: WebView2 nav_order: 2 -permalink: /WebView2/Customize-UserDataFolder +permalink: /Tutorials/WebView2/Customize-UserDataFolder +redirect_from: + - /WebView2/Customize-UserDataFolder --- # Customize the UserDataFolder diff --git a/docs/WebView2/Getting started.md b/docs/Tutorials/WebView2/Getting started.md similarity index 94% rename from docs/WebView2/Getting started.md rename to docs/Tutorials/WebView2/Getting started.md index ff81a76..d5ec389 100644 --- a/docs/WebView2/Getting started.md +++ b/docs/Tutorials/WebView2/Getting started.md @@ -2,7 +2,9 @@ title: Getting Started parent: WebView2 nav_order: 1 -permalink: /WebView2/Getting-Started +permalink: /Tutorials/WebView2/Getting-Started +redirect_from: + - /WebView2/Getting-Started --- # Getting Started diff --git a/docs/WebView2/Images/tbWebView2CreateEvent.png b/docs/Tutorials/WebView2/Images/tbWebView2CreateEvent.png similarity index 100% rename from docs/WebView2/Images/tbWebView2CreateEvent.png rename to docs/Tutorials/WebView2/Images/tbWebView2CreateEvent.png diff --git a/docs/WebView2/Images/tbWebView2InAForm.gif b/docs/Tutorials/WebView2/Images/tbWebView2InAForm.gif similarity index 100% rename from docs/WebView2/Images/tbWebView2InAForm.gif rename to docs/Tutorials/WebView2/Images/tbWebView2InAForm.gif diff --git a/docs/WebView2/Images/tbWebView2Properties.png b/docs/Tutorials/WebView2/Images/tbWebView2Properties.png similarity index 100% rename from docs/WebView2/Images/tbWebView2Properties.png rename to docs/Tutorials/WebView2/Images/tbWebView2Properties.png diff --git a/docs/WebView2/Images/tbWebView2References.png b/docs/Tutorials/WebView2/Images/tbWebView2References.png similarity index 100% rename from docs/WebView2/Images/tbWebView2References.png rename to docs/Tutorials/WebView2/Images/tbWebView2References.png diff --git a/docs/WebView2/Images/tbWebView2Sample0.png b/docs/Tutorials/WebView2/Images/tbWebView2Sample0.png similarity index 100% rename from docs/WebView2/Images/tbWebView2Sample0.png rename to docs/Tutorials/WebView2/Images/tbWebView2Sample0.png diff --git a/docs/WebView2/Images/tbWebView2Toolbox.png b/docs/Tutorials/WebView2/Images/tbWebView2Toolbox.png similarity index 100% rename from docs/WebView2/Images/tbWebView2Toolbox.png rename to docs/Tutorials/WebView2/Images/tbWebView2Toolbox.png diff --git a/docs/WebView2/Re-entrancy.md b/docs/Tutorials/WebView2/Re-entrancy.md similarity index 96% rename from docs/WebView2/Re-entrancy.md rename to docs/Tutorials/WebView2/Re-entrancy.md index 10bbfb2..86de5d8 100644 --- a/docs/WebView2/Re-entrancy.md +++ b/docs/Tutorials/WebView2/Re-entrancy.md @@ -2,7 +2,9 @@ title: Re-entrancy parent: WebView2 nav_order: 3 -permalink: /WebView2/Re-entrancy +permalink: /Tutorials/WebView2/Re-entrancy +redirect_from: + - /WebView2/Re-entrancy --- # Re-entrancy diff --git a/docs/Tutorials/WebView2/index.md b/docs/Tutorials/WebView2/index.md new file mode 100644 index 0000000..a6feea6 --- /dev/null +++ b/docs/Tutorials/WebView2/index.md @@ -0,0 +1,10 @@ +--- +title: WebView2 +parent: Tutorials +permalink: /Tutorials/WebView2 +redirect_from: + - /WebView2 +--- + +# WebView2 + diff --git a/docs/Tutorials/index.md b/docs/Tutorials/index.md new file mode 100644 index 0000000..b8d5f1e --- /dev/null +++ b/docs/Tutorials/index.md @@ -0,0 +1,6 @@ +--- +title: Tutorials +permalink: /Tutorials/ +nav_order: 3 +--- + diff --git a/docs/WebView2/index.md b/docs/WebView2/index.md deleted file mode 100644 index a7145a1..0000000 --- a/docs/WebView2/index.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: WebView2 -nav_order: 5 -permalink: /WebView2 ---- - -# WebView2 - diff --git a/docs/index.md b/docs/index.md index c6d9b5c..e40c665 100644 --- a/docs/index.md +++ b/docs/index.md @@ -19,20 +19,14 @@ permalink: / The [twinBASIC wiki](https://github.com/twinbasic/documentation/wiki) supplements this documentation with bleeding-edge community content. ## ActiveX + 1. [HOW TO: Create a Custom ActiveX Control with twinBASIC](https://nolongerset.com/create-activex-control-with-twinbasic/) _[by Mike Wolfe @nolongerset]_ 2. [HOW TO: Create a Tool Window in the VBIDE with twinBASIC](https://nolongerset.com/create-a-vbe-addin-with-twinbasic/) _[by Mike Wolfe @nolongerset]_ -## CustomControls -1. [Introduction](CustomControls/Introduction) -2. [Defining a CustomControl](CustomControls/Defining) -3. [Property sheet and object serialization](CustomControls/Properties) -4. [Painting / drawing to your control](CustomControls/Painting) -5. [Notes about the form designer](CustomControls/Form Designer) - -## WebView2 -1. [Getting Started](WebView2/Getting-Started) -2. [Customize the UserDataFolder](WebView2/Customize-UserDataFolder) -3. [Information about re-entrancy](WebView2/Re-entrancy) +## Tutorials + +1. [CustomControls](Tutorials/CustomControls) +2. [WebView2](Tutorials/WebView2) ## Language and IDE Features 1. [Overview of features new to twinBASIC](Features) (compared to VBx) From 0b90625f810e38a787e4e984770d32dd4ad3dc3f Mon Sep 17 00:00:00 2001 From: Kuba Sunderland-Ober Date: Sun, 15 Feb 2026 00:35:56 +0100 Subject: [PATCH 2/2] Add an array tutorial. --- docs/Tutorials/Arrays.md | 286 +++++++++++++++++++++++++++++++++++++++ docs/index.md | 5 +- 2 files changed, 289 insertions(+), 2 deletions(-) create mode 100644 docs/Tutorials/Arrays.md diff --git a/docs/Tutorials/Arrays.md b/docs/Tutorials/Arrays.md new file mode 100644 index 0000000..0bbc10a --- /dev/null +++ b/docs/Tutorials/Arrays.md @@ -0,0 +1,286 @@ +--- +title: Arrays +parent: Tutorials +permalink: /Tutorials/Arrays +--- + +# Arrays +{: .no_toc } + +Arrays come in two kinds: + +1. Fixed size arrays, whose size specification is a compile-time constant. + `Dim MyInts(10) As Integer` + `Dim MyLongs(10 To 19) As Long` +2. Dynamic arrays, who aren't initialized initially, and must be (re-)dimensioned prior to use. + `Dim MyLongs() As Long` + +Fixed size arrays have lower memory and runtime overhead than dynamic arrays. They perform better as small arrays -- up to 8 cache lines in size, or up to 512 bytes in size. + +In arrays larger than that, the overhead of a dynamic array becomes negligible when creating (dimensioning) the array. However, there is still slight runtime overhead on element access, independently of the size of a dynamic array. + +- TOC +{:toc} + +## Array Declaration Syntax + +Fixed size arrays can only be used for variables or class and UDT fields. +Dynamic arrays can be used for variables, fields, parameter types and return types. +A fixed size array can be passed as an argument accepting a dynamic array. + +> [!NOTE] +> +> Fixed size arrays cannot be used as return types directly. They can be returned when wrapped in a UDT. + +* Syntax for variable declarations in procedures + **Dim** | **Static** name **()** [ **As** type ] -- dynamic array + **Dim** | **Static** name **(** size [ **,** size ... ] **)** [ **As** type ] -- fixed array +* Syntax for procedure parameter types; only dynamic arrays are valid and both syntaxes below are equivalent + name **()** [ **As** type ] + name **As** type **()** +* Syntax for procedure return types; only dynamic arrays are valid + name **As** type **()** +* Syntax for field declarations in classes + **Dim** | **Private** | **Protected** | **Public** name **()** [ **As** type ] -- dynamic array + **Dim** | **Private** | **Protected** | **Public** name **(** size [ **,** size ....] **)** [ **As** type ] -- static array +* Syntax for field declarations in types (UDTs) + name **()** [ **As** type ] -- dynamic array + name **(** size [ **,** size ....] **)** [ **As** type ] -- static array + +Each size specification is a range, but the lower bound is optional and defaults to currently active **Option Base**: + +- ubound, e.g. + `Dim A(10, 20)` +- lbound **To** ubound -- range, inclusive of both bounds, e.g. + `Dim A(1 To 10, 1 To 20)` + +Both variants of size specifications can be mixed in one declaration, e.g. +`Dim B(10, 1 To 20)` + +Here is how **Option Base** controls the default lower bound of a dimension: + +```vb +Option Base 0 +Dim A(10, 20) ' is equivalent to... +Dim A(0 To 10, 0 To 20) ' i.e. a 21 x 11 array + +Option Base 1 +Dim A(10, 20) ' is equivalent to... +Dim A(1 To 10, 1 To 20) ' i.e. a 20 x 10 array +``` + +Only the dynamic arrays can be passed as procedure arguments: + +```vb +Sub OkSub1(data() As Byte) ' Dynamic array parameter +Sub OkSub2(data As Byte()) ' Alternate syntax + +Sub BadSub1(data(10) As Byte) ' Invalid, fixed array types are not allowed as parameters... +Sub BadSub2(data As Byte(10)) ' ... in neither syntax +``` + +## Dimensioning Dynamic Arrays + +A dynamic array is uninitialized after declaration. It cannot be used in any way other than to be dimensioned. Dimensioning is performed by the **ReDim** statement: + +```vb +Dim array() +Debug.Assert IsArrayInitialized(array) = False +Debug.Print LBound(array) ' raises a runtime error since the array is uninitialized, + ' and no operations are valid on it other than a ReDim + +ReDim array(1 to 10) ' now the array is initialized +Debug.Assert IsArrayInitialized(array) = True +Debug.Assert LBound(array) = 1 +Debug.Assert UBound(array) = 10 +``` + +**ReDim** has two operating modes: by default, it discards the existing data in the array. Optionally, it can preserve the existing data to the extent that new dimensions allow it. + +Syntax: + +* **ReDim** [ **Preserve** ] name **(** size [ **,** size ...] **)** + +> [!IMPORTANT] +> +> Only the upper bound of an array dimension can be changed with **ReDim Preserve**. +> Non-preserving **ReDim** allows arbitrary changes. + +```vb +Dim a() As Long + +ReDim a(1 To 2) ' Initial dimensioning +a(1) = 10 +a(2) = 20 + +ReDim Preserve a(1 To 3) ' Change of an upper bound of 1st dimension +Debug.Assert a(1) = 10 +Debug.Assert a(2) = 20 +Debug.Assert a(3) = 0 + +ReDim Preserve a(2 To 3) ' Causes a runtime error + +ReDim a(5 To 8) ' Change of both bounds of 1st dimension while losing data +Debug.Assert a(5) = 0 +``` + +## Determining Array Dimension Bounds + +Every dimension of an *initialized* array has an associated lower and upper bound. These bounds are accessed with the **LBound** and **UBound** functions. + +```vb +Dim array(1 To 10, 3 To 20) +Debug.Assert LBound(array) = 1 ' 1st dimension by default +Debug.Assert LBound(array, 1) = 1 ' 1st dimension +Debug.Assert LBound(array, 2) = 3 ' 2nd dimension +Debug.Assert UBound(array, 2) = 20 ' 2nd dimension, upper bound' +``` + +## Determining Array Size + +An attempt to use **LBound** or **UBound** on an uninitialized array causes a runtime error. Thus, a function that determines the number of elements in a given dimension of an array, must first check if the array is initialized: + +```vb +Sub ArrayLen(Of T)(array() Of T, ByVal dimension% = 1) As Long + ' zero is the default return value + If IsArrayInitialized(array) Then + Return 1 + UBound(array, dimension) - LBound(array, dimension) + End If +End Sub +``` + +See also [Efficient low-level access of a 1D array](#efficient-low-level-access-of-a-1d-array). + +## Array Element Access + +To access array elements, indices for all dimensions should be provided as a parenthesized list after the name of the array variable: + +```vb +Dim array(1 To 10) As Long + +array(1) = 42 +Debug.Assert array(1) = 42 + +Dim array2(1 To 10, 1 To 2) As Long +array(1, 2) = 42 +Debug.Assert array(1, 2) = 42 +``` + +Array elements are initialized to zero/null, just as all the other types are in twinBASIC: + +```vb +Dim intArray(1 To 10) As Integer +Debug.Assert intArray(1) = 0 AndAlso intArray(10) = 0 + +Dim strArray(20 To 25) As String +Debug.Assert strArray(20) = vbNullString +``` + +## Returning Arrays + +Any array can be returned as a dynamic array: + +```vb +Function Fn1() As Long() + Dim array1() As Long + Dim array2(11) As Long + Return array1 + Return array2 +End Function +``` + +To return a fixed size array, it has to be wrapped in a UDT: + +```vb +Type Wrapper + array(11) As Long +End Type + +Function Fn2() As Wrapper + ' The procedure name is used to access the returned value + Fn2.array(5) = 10 +End Function + +Sub Test() + Dim arr As Wrapper = Fn2() + Debug.Assert arr.array(5) = 10 +End Sub +``` + +## Efficient low-level access of a 1D array + +In twinBASIC, array types are implemented as pointers to a pointer to the Windows API **SAFEARRAY** structure. + +This can be leveraged to efficiently access: + +- the count of elements in the 1st dimension +- as the pointer to the data (to the 1st element in the array) +- the size of the array in bytes + +```vb +Function ArrayLen(Of T)(array() As T) As Long + Dim p As LongPtr + GetMemPtr(VarPtr(array), p) + If p <> 0 Then ' if the array is initialized + #If win64 Then + GetMem4(p + 24, Len) + #Else + GetMem4(p + 16, Len) + #End If + End If +End Function + +Function ArrayPtr(Of T)(array() As T) As LongPtr + Dim p As LongPtr + GetMemPtr(VarPtr(array), p) + If p <> 0 Then + #If win64 Then + GetMemPtr(p + 16, Ptr) + #Else + GetMemPtr(p + 12, Ptr) + #End If + End If +End Function + +Function ArrayBytes(Of T)(array() As T) As Long + Return ArrayLen(array) * LenB(Of T) +End Function + +``` + +These functions are useful to pass arrays and array counts to external **Declare**-d procedures. For example: + +```vb +Declare Sub SaveData Lib "mylib" (ByVal ptr As LongPtr, ByVal count&) +Declare Sub WriteData Lib "mylib" (ByVal ptr As LongPtr, ByVal numBytes&) + +Sub Save(array() As Long) + Debug.Assert ArrayBytes(array) = ArrayLen(array) * 4 ' 4 = size of a Long + SaveLongData(ArrayPtr(array), ArrayLen(array)) +End Sub + +Sub Write(array() As Long) + WriteData(ArrayPtr(array), ArrayBytes(array)) +End Sub +``` + +Without these functions, this would have been more cumbersome: + +```vb +Sub Save(array() As Long) + If IsArrayInitialized(array) Then + SaveLongData( _ + VarPtr(array(LBound(array))), _ + 1 + UBound(array) - LBound(array)) + Else + SaveLongData(0, 0) ' ArrayLen, ArraySize, and ArrayPtr would + ' return 0 for an uninitialized array + End If +End Sub +``` + + diff --git a/docs/index.md b/docs/index.md index e40c665..ca2c5f4 100644 --- a/docs/index.md +++ b/docs/index.md @@ -25,8 +25,9 @@ The [twinBASIC wiki](https://github.com/twinbasic/documentation/wiki) supplement ## Tutorials -1. [CustomControls](Tutorials/CustomControls) -2. [WebView2](Tutorials/WebView2) +1. [Arrays](Tutorials/Arrays) +2. [CustomControls](Tutorials/CustomControls) +3. [WebView2](Tutorials/WebView2) ## Language and IDE Features 1. [Overview of features new to twinBASIC](Features) (compared to VBx)