twinBASIC Update: February 5, 2023

On April 23, 2021, I helped Wayne Phillips introduce the world to twinBASIC at the Access DevCon Vienna conference.  I boldly predicted that twinBASIC (along with the Monaco editor) would replace VBA and its outdated development environment by 2025.  With that goal in mind, this weekly update is my attempt to keep the project fresh in the minds of the VBA development community.

Every Sunday, I will be providing updates on the status of the project, linking to new articles discussing twinBASIC, and generally trying to increase engagement with the project.  If you come across items that should be included here, tweet me @NoLongerSet or email me at mike at nolongerset dot com.

Here are some links to get involved with the project:


Highlights

ActiveX Support Returns After Major Rewrite

Prior to the release of BETA 238–which included a major rewrite of twinBASIC's ActiveX implementation, someone in Discord asked Wayne how it was going.  Here's Wayne's response:

It's getting there.  It's a big rewrite of the Ax-wrappers and UserControls support though, so I'm trying to test as much as reasonably possible to prevent major regressions.

I first wrote an interim proxy ActiveX control that can be placed between VB6 and any ActiveX control, and this allows me to monitor the (stupidly complex) two-way comms between the two endpoints.  So I now know that the new implementations are significantly closer to the VB6 implementations, rather than the guess work that was previously used.

This has been hugely beneficial, but of course has been rather tedious.

Windowless Ax controls are now working, more events are implemented, and generated controls can now be used properly in other hosts (e.g. VB6, or Access) and the controls show correctly in design mode too rather than the previous green-window of earlier versions.

Essentially, it sounds like Wayne built a glass box (his "interim proxy ActiveX control") to look inside what was previously the black box of VB6's ActiveX control implementation.  

My assumption is that his first round of ActiveX control support was guided primarily by implementing the relevant COM interfaces.  In theory, this should have been enough.  And if developers relied solely on documented features of COM, it might have been.  In particular, if all the existing VB6 code relied only on the implicit contracts with the COM interfaces, then a new implementation that fulfilled that same interface contract from the other side should have worked seamlessly.

But, of course, there is a lot of VB6 code out there that relies not just on the COM interfaces, but on VB6's particular implementation of those interfaces.  (Much of this was to work around the safeguards built into the language that made direct memory management intentionally difficult.)  With a code base as large as VB6's, the only way you can get to 100% backwards compatibility is to match VB6's ActiveX implementation details.

Brief aside: One of the advantages of using interfaces when building code is that the calling code does not depend on the implementation of the interface.  In theory, ActiveX controls, being a COM technology, are driven primarily by interfaces (e.g., IUnknown, IDispatch, etc.).  Thus, it should be relatively straightforward to replace one implementation (VB6's ActiveX support) with another (twinBASIC's ActiveX support).  

In theory.  

The real world is messier.  Matching an implementation of an existing interface with a new implementation is trickier than the theory makes it out to be.  Matching an existing implementation with a goal of providing 100% backwards compatibility is even trickier.  Just ask Microsoft.

In any event, Wayne's approach of creating an ActiveX control to more closely monitor what's actually happening at the lowest levels of implementation increases my confidence that he can achieve his 100% backwards compatibility goal.

If you're still not sure what this whole black box/glass box metaphor is all about, check out my article on the Watch() function that I created.  It has nothing to do with ActiveX, but it's a good example of the concept of turning a black box into a glass box:

How to Set a Breakpoint Inside of an Access Query
Did you ever want to set a breakpoint inside of an executing query? How about inside a form event property? This trick lets you do it.

Around the Web

vbInvoke Project

Over on GitHub, Greedquest posted some updates to his vbInvoke project, which he originally wrote in C# before porting it to VBA and then twinBASIC.

Here's a summary of the project from the GitHub readme:

Library for calling methods in VBA modules with 3 key benefits:

• Host agnostic (unlike Application.Run)
• Works with Standard .bas Modules (unlike CallByName that calls classes)
• Can call public or private methods

Under the hood it uses the same technique as Rubberduck's test execution engine to access the addresses of the public and private methods, ported from C# to VBA to twinBASIC (thanks RD team & Wayne for all the help).

tbShellLib Updates

Jon Johnson (aka, fafalone) updated his twinBASIC Shell Library project.

Here's his comment from Discord:

I've posted updates to tbShellLib (major additions plus the OleAutomation(False) attribute on all interfaces), and ucShellBrowse, with 12.0 adding some features in addition to ShellControls.twinproj now ready to play around with compiling to Active-X DLL (though if you're using it in tB stick to the twinpack or tbcontrol)

(also updated tbShellLib on the package manager server)

Where is the Source Code?

This question over on GitHub sparked a longer discussion about the business side of twinBASIC.

If you've been following from the beginning, you'll know that twinBASIC is a closed-source, commercial project from Wayne Phillips.  GitHub is used as a bug-tracking database and for community discussions regarding the language design.  Wayne plans to open source the twinBASIC IDE eventually, but has not made the same commitment regarding the language compiler itself.

This situation is a legitimate concern for developers who might be inclined to use twinBASIC in commercial projects.  

User kismert1 summed up the challenge well:

I understand why Wayne [is] doing it this way, but still. We all hope this language takes off, and becomes commercially viable. But under the current circumstances, if that happens the tB user community will still have to deal with the uncomfortable feeling that they could get locked-in to a defunct language platform (the same thing that VB6 and Access users face). One day, support could just go away (or get crippled). Eventually, clients can't properly be serviced. The client is then locked in, and sooner or later has to face an expensive migration to some other (hopefully more permanent) platform. That's a story I want to move away from with Access.

It's a bit of a chicken-and-egg problem.  

Without the possibility of a commercial pay-off, there would have been zero very little incentive for Wayne to dedicate two-plus years of full-time work to this endeavor (so far).  However, the point above will be a strong disincentive to adoption among a certain type of user (to be honest, the exact type of user most likely to be willing to pay for a full license).

Wayne understands this and has pledged to put the source code into escrow following the v1.0 release (if not before).  He also isn't ruling out the possibility of twinBASIC going open source in the future:

Having spent a not-insignificant portion of my life on this project over the last few years, I most certainly would not want to see tB fail at this stage, and I am determined to ensure that does not happen.

Commercially, things are working out OK right now... we're roughly where I would expect to be at this point (given the BETA state).  I would love to see tB open-sourced eventually, but I suspect that it would require some sort of corporate sponsorship, or thinking outside-the-box... perhaps something like a community buy-out.   There's so many possibilities, so certainly don't discard the possibility of tB going open-source at some point in the future.

The scarier prospect, though, might be this scenario:

[I]t's a fair question what's going to happen if MS shows up at Wayne's door with a 7-8 figure check in one hand and lawsuit service in the other...

I certainly hope it never comes to that, but Wayne's got a family.  I know what I would do in that situation...

Changelog

Here are the updates from the past week.  You can also find this information by visiting the GitHub twinBASIC Releases page.

Releases · WaynePhillipsEA/twinbasic
Contribute to WaynePhillipsEA/twinbasic development by creating an account on GitHub.

WARNING: The following two issue is present in BETA builds 202 - 242 (the latest build as of publication):

  • there are known memory leaks in these versions, so memory usage will be higher than normal

FURTHER WARNING: Builds 239 - 241 have a known bug that makes the IDE fail if your regional settings are not set to English.  The bug is fixed in the latest build.

BETA 238

  • improved: major rewrite of ActiveX extender and UserControl implementations to better match VBx behaviours.  Expect a few regressions.
  • fixed: off-by-one bug in writing UserControl property bags, leading to final written value sometimes not being persisted
  • improved: tB generated ActiveX controls can now be used in VB6, and other hosts (note: remember to set project setting 'Register DLLs to HKEY_LOCAL_MACHINE' appropriately)
  • added: Windowless support for ActiveX/UserControl (including BackStyle transparent support, excluding ClipBehavior/HitBehavior/MaskPicture support)
  • renamed: UserControl.ResizeToContainer property to ForceResizeToContainer (typically only needed for ToolWindows)
  • fixed: some DPI issues for generated Ax controls
  • fixed: (regression/BETA224) double-extending an Interface from IDispatch causes build (typelib) error [ fafalone, discord ]
  • fixed: parser edge case where a space between a function name and the opening parenthesis could be misinterpreted (e.g. Split (a,b) was failing)
  • fixed: some ActiveX/UserControl z-ordering issues
  • fixed: WM_PAINT handling now allows for wParam HDC passing (for VBCCR 'Transparent' property support)
  • improved: ActiveX/UserControl Ambient properties now implemented, and AmbientChanged event now implemented
  • fixed: importing of floating point values from VBP form properties was not always working
  • fixed: (regression/BETA230) setting ActiveX control Font properties via the form designer could cause form errors
  • fixed: form designer Font properties on CodeJock Ax controls would show an empty list due to empty IPerPropertyBrowsing
  • fixed: dispinterface optional arguments without a defined default value were not being treated as optional

BETA 239

  • fixed: locally defined Interface definitions were outputted to generated type libraries with an underscore prefix [ fafalone, discord ]
  • improved: added attribute [ OleAutomation(Boolean) ], default: True, for controlling the TYPEFLAG_FOLEAUTOMATION flag in type library generation

BETA 240

  • added: compiler warning TB0012 "possible misuse of hexadecimal literal notation"
  • fixed: auto-generated class members would sometimes have invalid signatures [ fafalone, discord ]
  • improved: export source feature now auto-retries when writing to a file before failing (4 seconds retry) [ fafalone, discord ]
  • fixed: changes to Control.Font properties were not being reflected live at runtime [ sokinkeso, discord ]
  • fixed: (regression) lightweight controls rendering in back-to-front order [ sokinkeso, discord ]
  • fixed: (regression) lightweight controls events not always firing [ sokinkeso, discord ]

BETA 241

  • fixed: (regression/BETA240) internal error with the latest changes to font handling  [ fafalone, discord ]

BETA 242

  • fixed: (regression/BETA239) problem preventing the IDE from working when the system ANSI codepage was not English