====== Demo Script: DevCon 2024 ======
* I have 25 minutes for the demo portion:
* 0:01: Download and open twinBASIC
* 0:02: Customize add-in name and description
* 0:04: Create the tool window controls
* 0:05: Edit the Code in myToolWindow
* 0:07: Test in Access
* 0:10: Explain Strongly-typed collections and copy ''BuildStronglyTypedCollection()'' function
* 0:15: Bring in other dependencies
* 0:16: Test in Access
* 0:18: Test in Barebones Access
* 0:22: Convert fafalone's WinDevLib package
* 0:24: Build 64-bit version
* 0:25: Explain ''regsvr32'' registration; mention InnoSetup
===== Download and Save Sample Code =====
- Download [[https://github.com/twinbasic/twinbasic/releases/tag/beta-x-0504|twinBASIC BETA 504]]
- Extract from Zip folder
- Open twinBASIC > **Sample 4**
- Enter Project Name: ''Demo2024'' (//Do not put spaces in the name//)
- Save as: ''%tmp%\Demo2024\Demo2024.twinproj''
- Navigate to: ''%tmp%''
- Create folder named: ''Demo2024''
- Filename: ''Demo2024.twinproj''
===== Customize the Addin Name and Description =====
Next, let's customize the friendly name and description of our addin. This is the info that appears in the VBA Add-in Manager dialog box.
- Go to **dllRegistration.twin** > **DllRegisterServer**
- In the "FriendlyName" line, replace //AddinProjectName// with ''"DevCon 2024 Demo"''
- In the "Description" line, replace //AddinProjectName// with ''"Create a strongly-typed collection class from an existing VBA class object."''
- Save the project
- Build the project
- Launch ''M:\Repos\NLS\DevCon2024\DevCon2024.accdb''
- Switch to VBA: Ctrl + G
- Dock the add-in window
- Go to "Add-Ins" > "Toggle myToolWindow Visibility"
- Go to "Add-Ins" > "Add-in Manager"
* Point out the "DevCon 2024 Demo" item with description below
- Close "Add-In Manager" window
===== Create the Tool Window Controls =====
Next, we're going to customize the controls that appear on the tool window. I'll explain what these controls will be used for in a minute. For now, all you need to know is that we are adding two text boxes, a command button, and a label to hold a version number.
- Open myToolWindow.tbcontrol
- Select all controls and delete them
- Click DIAGNOSTICS error to go to myToolWindow.twin and **delete all dead code**
- Select form and set the following properties:
* Height: 1700
* Width: 2550
- Create a text box and set the following properties:
* Name: ''tbObjName''
* Anchors > Right: [√] True
* Height: 300
* Left: 150
* Text: //{blank}//
* TextHint: ''Object Class Name''
* Top: 150
* Width: 2250
- Create a text box and set the following properties:
* Name: ''tbCollName''
* Anchors > Right: [√] True
* Height: 300
* Left: 150
* Text: //{blank}//
* TextHint: ''Collection Class Name''
* Top: 600
* Width: 2250
- Create a button and set the following properties:
* Name: ''btnCreateClass''
* Anchors > Right: [√] True
* Caption: ''Create Collection Class''
* Height: 450
* Left: 150
* Top: 1050
* Width: 2250
- Create a version label
* Caption: Version {hhmm}
===== Edit the Code in myToolWindow.twin =====
- Delete the ''Timer1_Timer()'' and ''HelloWorld_Click()'' subroutines
- Add a Click event handler for btnCreateClass using the code below
Private Sub btnCreateClass_Click()
MsgBox "Object class name: " & Me.tbObjName.Text & vbNewLine & _
"Collection class name: " & Me.tbCollName.Text, vbInformation, "Create Class"
End Sub
===== Test the Updated Addin =====
- Make sure Access is closed then **Build** the tB project
- Reopen Access and switch to VBA
- Enter sample text ''oVehicle'' for object class name and ''collVehicles'' for collection class name then click [Create Collection Class]
===== Strongly-Typed Collection Class =====
Now, let's talk about what this add-in will actually, you know, //do//.
The purpose of the add-in is to encapsulate the ''BuildStronglyTypedCollection()'' function as described here: [[https://nolongerset.com/strongly-typed-collection-classes-the-easy-way/|Strongly-Typed Collections: The Easy Way]]
I put a link to this article in the Resources page for today's presentation. If you've never heard of strongly-typed collection classes, I recommend you read up on them later.
For our purposes, the important thing to know about them is that you CANNOT build them in the VBA editor. They require setting a couple of hidden code attributes that only appear when you export the code module to a text file.
As you can imagine, manually jumping through those hoops is inefficient and error-prone. The existing code I wrote in VBA does automate the process, but it requires importing several additional dependencies. Our VBE add-in will be a direct replacement for the ''BuildStronglyTypedCollection()'' function.
===== Copy the VBA Code Into twinBASIC =====
- Create a new module named MyModule.twin
-
===== Build and Test the Addin on a Different Machine and Bitness =====
The following instructions assume you are building on a machine with 32-bit Office (mjw20), but installing on a machine with 64-bit Office (e.g., gbm18):
- Ensure "**win64**" is selected in dropdown
- **File** > **Build**
- I copied ''M:\Repos\NLS\DevCon2024\Build\DevCon2024_win64.dll'' to ''%fb%\12114\DevCon2024_win64.dll'' (I will test registering it tomorrow on gbm18)
- Open a non-admin cmd prompt
- Run: ''regsvr32 DevCon2024_win64.dll''
* Receive message: "DllRegisterServer in DevCon2024_win64.dll succeeded."
- Open Word (or Excel) - The add-in appears.
===== Copy and Paste Working VBA Code into twinBASIC =====
- Add a standard code module named "MyModule":
- Right-click Sources > **Add** > **Add Module (.TWIN supporting Unicode)**
- Go to [[nls>strongly-typed-collection-classes-the-easy-way|Strongly-Typed Collections: The Easy Way]]
- Copy and paste the [[nls>getguidbasedtemppath|GetGuidBasedTempPath code]]
- Copy and paste the [[nls>text-files-read-write-append|FileWrite code]]
- Handle "Unrecognized datatype symbol 'Scripting'" error in DIAGNOSTICS pane:
- Go to **Project** > **References**
- Switch to "Available COM References" tab
- Search for "script" and then click the "Microsoft Scripting Runtime" reference
- Click [Save Changes]
===== Add fafalone's WinDevLib Package for API Calls =====
- **Project** > **References...**
- Switch to "Available Packages" tab
- Search for "windows"
- Check box next to "[√] Windows Development Library for twinBASIC vX.Y.ZZZ"
* The package will immediately begin downloading in the background
* When the download finishes, the name will change to "[√] [IMPORTED] Windows Development Library for twinBASIC vX.Y.ZZZ"
* NOTE: "[[https://github.com/fafalone/WinDevLib?tab=readme-ov-file#guide-to-switching-from-oleexpimptlb|WinDevLib for Implements]]" is a different package
- Click [Save Changes]
- Comment out (or delete) API `Declare` lines throughout the project
* Be aware that if you used non-standard `Alias` names, you may need to adjust your API calls to match the standard versions used in WinDevLib
* **myAddIn.twin**:
* Delete ''Private Type RECT'' structure
* Delete ''GetClientRect()'' function declare
* **InterProcess.twin**:
* Delete ''GetCurrentProcessId()'' function declare line...
* ...through ''Type UUID'' structure
* **MyModule.twin**:
* Delete ''Sleep'' sub declare
* Comment out ''CoCreateGuid'' function declare and highlight the failure to compile due to the stricter typing of ''id As UUID'' in WinDevLib versus ''id As Any'' in my code
* Uncomment the ''CoCreateGuid'' function to show that explicit API declares override the WinDevLib versions
- Pass Unicode strings directly to API declare functions
* Most string-related API functions have ANSI and Unicode versions ("A" and "W" for "ANSI" and "Wide", respectively)
* Lots of legacy VB6/VBA code use the ANSI version of API functions
* WinDevLib [[https://github.com/fafalone/WinDevLib?tab=readme-ov-file#windevlib-api-standards|encourages the use of Unicode versions]] by default
* This means that code that passes input strings to API functions may require wrapping the string in `StrPtr()` (or removing `StrPtr()`) from your existing code
* [_] Remove ''StrPtr()'' from calls to ''FindWindowEx()'' in InterProcess.callerApplicationObject
* [_] Convert final argument from ''0&'' to ''vbNullString'' for calls to ''FindWindowEx()'' in InterProcess.callerApplicationObject