====== 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