twinBASIC Update: May 13, 2026
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 Monday week, 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, please leave a comment below.
Here are some links to get involved with the project:
- Custom twinBASIC IDE Installation Guide
- twinBASIC Discord Server (chat about the project)
- twinBASIC Wiki (list of new features not in VBx)
- GitHub Issue Tracker (report bugs)
- twinBASIC/VBx LinkedIn Group
Highlights
Chromium Embedded Framework (CEF) Support
*Generated with Claude Opus 4.7.
BETA 980 landed with Chromium Embedded Framework support as its headline feature—a commissioned addition that ships as a full package with a working sample project.
The most visible architectural difference between CEF and WebView2 is process ownership. WebView2 spawns separate msedgewebview2.exe helper processes managed by the system-installed Edge WebView2 Runtime, which means your application relies on an external component that Microsoft updates on its own schedule. CEF, by contrast, reuses your own application's executable for its subprocesses and ships its runtime files alongside your app, giving you full control over the browser version you deploy against.
That control comes with a tradeoff: distribution size.
WebView2 apps stay lean because the runtime lives on the user's machine, while CEF apps must bundle the Chromium runtime themselves (a non-trivial download). In exchange, CEF apps work on locked-down systems without the WebView2 Runtime installed, behave identically across machines regardless of what Microsoft pushes out, and avoid the class of bugs that appear when a silent Edge update changes rendering behavior overnight. For kiosk software, offline deployments, and enterprise environments with strict update policies, that predictability is often worth the extra megabytes.
The runtime itself comes in three flavors.
twinBASIC supports CEF runtimes v49, v109, and v145, targeting Windows XP+, Windows 7+, and Windows 10+ respectively — though only v145 is recommended for general internet-facing use, since the older builds carry unpatched Chromium vulnerabilities. Runtime files install to %LocalAppData%\twinBASIC_CEF_Runtime\ by default, with EnvironmentOptions.BrowserExecutableFolder available to redirect the control to a portable side-by-side deployment. The CEF version chosen at compile time (via the package reference) must match the runtime shipped at deploy time, and bitness must match the application.
One more strategic angle is worth noting: CEF is cross-platform-ready.
Unlike WebView2, which is Windows-only, CEF runs on Windows, Linux, and macOS — which dovetails nicely with the broader community interest in eventual Linux targets for twinBASIC itself. CEF also permits deeper runtime integration than WebView2's locked-down object model allows, opening the door to hosting twinBASIC code inside the renderer/JavaScript process in the future. The CEF tutorials cover the most common patterns — getting started, hosting local web assets, JavaScript interop, and a case study that drives Microsoft's Monaco editor from twinBASIC.
The subprocess model also has direct code implications.
Because CEF launches copies of your own executable as renderer, GPU, and utility processes, twinBASIC needed a mechanism to detect those launches before your normal startup logic runs. That is the purpose of the new [RunBeforeStartupObject] attribute: a package can inject a procedure that runs ahead of Sub Main or the startup object, inspect the command line, and return True to continue to normal startup or False to exit the subprocess cleanly. The attribute is general-purpose and will likely find uses well beyond CEF itself — anywhere a package needs to hook process initialization before user code takes over.
A rapid BETA 981 follow-up added CreateInitialized and an Initialize() method for deferred browser setup. Once the packages are battle-tested, the twinBASIC IDE itself is slated to migrate to CEF.
docs.twinbasic.com Now a Near-Complete Reference Site
*Generated with Claude Opus 4.7.
Community contributor okas_o spent the week transforming twinBASIC's documentation from partial coverage into a genuine reference site.
The scope is hard to overstate. In seven days, okas_o completed documentation for the entire VBA package (FileSystem, DateTime, Financial, Math, Strings, Collection, Compilation, Constants, Conversion, ErrObject, ExpressionService, Information, Interaction, and the default hidden module), the full VBRUN package, and every control in the VB package. Coverage then extended outward to the WebView2, CEF, Assert, and CustomControls packages, each accompanied by tutorial pages derived from the sample projects that ship with twinBASIC.
Language reference coverage saw a parallel expansion.
All Statements and Operators are now documented, along with twinBASIC-specific enhancements to Class, Continue, Dim, Function, Property, Sub, and Type, plus the Alias, Delegate, and Handles keywords. Orientation landing pages were added for the VB, VBA, and VBRUN packages, a Packages overview page was written to aid navigation, and the glossary was extended with terms drawn from VBA documentation. Server-side Rouge syntax highlighting for twinBASIC code was also added, producing properly highlighted code blocks without requiring JavaScript in the reader's browser.
The community also pitched in on accuracy.
wqweto caught that Collection.KeyCompareMode defaults to vbTextCompare rather than vbBinaryCompare for VBx compatibility, and bclothier clarified that And, Or, and Not are strictly bitwise operations — Booleans are treated as integers at the bit level, a nuance that has produced subtle "dirty boolean" bugs in VBx codebases for decades. Both corrections were applied the same day they were raised. wqweto also surfaced that twinBASIC extends Implements to accept multiple interfaces on a single line, a tB-specific behavior now captured in the reference.
CSS styling for the new syntax highlighter remains open for community contribution, as does deeper narrative content for sections currently covered at baseline level.
Discord Chat Summary
* Auto-generated via Claude-Sonnet-4.6
Overview
The week's headline was the BETA 980 release, which introduced Chromium Embedded Framework (CEF) support as a major commissioned addition and a new [RunBeforeStartupObject] attribute. A rapid BETA 981 follow-up addressed community requests around CEF initialization, and waynephillipsea closed the week by announcing LLVM as the next development focus. In parallel, community contributor okas_o delivered a remarkable documentation sprint that brought twinBASIC's reference coverage from partial to near-complete in under seven days.
BETA 980: CEF Integration
- CEF project support arrived as a commissioned feature, accompanied by a new package, sample project, and documentation. waynephillipsea published a setup guide covering CEF runtime requirements and linking to download resources.
- A key behavioral difference from WebView2 was explained: WebView2 spawns separate
msedgewebview2.exesubprocesses, whereas CEF subprocesses reuse the host application's own executable. This necessitated the new[RunBeforeStartupObject]attribute, which allows a package to inject a procedure that intercepts subprocess launches beforeSub Mainor the startup object is reached. - waynephillipsea provided a usage example showing the function returning
Falseto exit a subprocess early andTrueto continue normally to the startup object — with a note that the attribute has potential uses beyond CEF.
BETA 981: Rapid CEF Follow-Up
- Responding to a community request for deferred browser initialization, waynephillipsea added
CefBrowser.CreateInitialized(defaulting toTrue) and a correspondingInitialize()method within days of the BETA 980 release, enabling scenarios such as deferred loading or private browsing sessions. - Similar lazy initialization support for the WebView2 component was confirmed as planned.
- waynephillipsea noted that once CEF packages are more thoroughly tested, the twinBASIC IDE itself will migrate to them, at which point the IPC performance improvements from earlier internal work will be more directly demonstrable.
LLVM: Next on the Roadmap
- Immediately following the BETA 980 release, waynephillipsea announced: "Next up: LLVM" — generating significant community enthusiasm around smaller binaries and faster execution speeds.
- Community members flagged LLVM as particularly important for performance-sensitive projects, with a longer-term Linux target also noted as a desirable downstream benefit.
Language Features & API Interop
- fafalone questioned whether warning TB0026 (implicit conversion to delegate type) should be on by default, noting that delegates are almost universally assigned from
GetProcAddress. waynephillipsea confirmed the warning is intentional, and previewed a cleaner future syntax —Something = GetProcAddress(hLib, "Something") As DelegateSomething— crediting wqweto for the idea. - wqweto identified that direct casting from
LongPtrto an interface viaCType(Of IInterface)(lPtr)is not yet supported and produces a codegen error. The current workaround using WinDevLib'sTType(Of T)is functional but verbose. A related limitation was surfaced: generic UDTs only resolve correctly when both the UDT and interface are declared in the same scope, not across package boundaries — a bug flagged for a future fix. - A thread on converting C
char**returns (specifically MariaDB'smysql_fetch_row) to VB strings drew contributions from wqweto and deletedewd, who refined pointer-enumeration approaches and clarified thatSysReAllocStringcan be declared withoutAs Stringfor VB6/tB compatibility — though for binary field data,mysql_fetch_lengthsshould be used rather than relying on null termination.
Graphics, Performance & Cross-Architecture Builds
- alaskandruid investigated high RAM consumption (~900MB per 1.5MB BMP) when running a DirectDraw project in the IDE, ultimately tracing the problem to the twinBASIC DEP host process rather than application code — compiled executables showed only ~12MB. waynephillipsea requested a minimal repro in the bugs channel.
- Separately, switching from
Collectionto arrays for thousands of tileset entries yielded a significant improvement in both memory usage and load time — a practical illustration of data-structure choice impacting performance in larger projects. - fafalone confirmed DirectDraw still functions in tB including in 64-bit, while deletedewd advocated Direct2D as a modern alternative requiring no external DLL distribution. fafalone's D2DSamples repository was highlighted as a ready reference covering Direct2D, DirectWrite, DirectComposition, Direct3D 12, OpenGL, and WIC.
- bclothier confirmed that 32-bit and 64-bit builds from a single
.twinprojfile are straightforward in tB — requiring only an IDE toolbar switch — withDeclarestatement updates being the primary consideration for mixed-architecture codebases.
Documentation Sprint
- Community contributor okas_o completed documentation for the entire VBA package (FileSystem, DateTime, Financial, Math, Strings, Collection, Compilation, Constants, Conversion, ErrObject, ExpressionService, Information, Interaction, and the default hidden module), the VBRUN package, and all controls in the VB package — finishing all three core packages by May 11.
- Coverage was extended to the WebView2, CEF, Assert, and CustomControls packages, each with accompanying tutorial pages. Orientation landing pages were written for VB, VBA, and VBRUN, and a Packages overview page was added for navigation. The glossary was expanded with terms from VBA documentation.
- All Statements and Operators are now documented, along with twinBASIC-specific enhancements to
Class,Continue,Dim,Function,Property,Sub,Type, and theAlias,Delegate, andHandleskeywords. Server-side Rouge syntax highlighting for tB code was also added, with CSS color styling noted as a future task open for community contributions. - Two accuracy corrections were applied from community review: wqweto caught that
Collection.KeyCompareModedefaults tovbTextCompare(notvbBinaryCompare) for VBx compatibility, and bclothier clarified thatAnd/Or/Notare strictly bitwise operations — Booleans are treated as integers at the bit level — an important nuance documented with a note about the "dirty boolean" edge case that has caused subtle bugs in VBx historically.
Conclusion
BETA 980's CEF integration and the swift BETA 981 follow-up show the project maintaining active development momentum, while the announcement of LLVM as the next focus signals a major step toward the performance and binary size improvements the community has long anticipated. okas_o's documentation effort stands as one of the most impactful single-contributor weeks in the project's history, bringing the reference site to a level of coverage that meaningfully lowers the barrier for new developers. With cross-architecture builds confirmed as low-friction, graphics APIs well-documented via fafalone's sample repositories, and core language interop patterns actively refined, twinBASIC continues to mature as a practical platform for both VB6 migration work and greenfield development.
Around the Web
API hooking module w/ trampoline
Posted by fafalone in show-and-tell:
This is [a] generic module for API hooking (redirecting an API call to your own function) that includes a "trampoline" that lets you call the original procedure after your redirect has run, using a delegate and the address supplied by the hooking module.
This was 99% done by Claude except using the new tB delegate functionality to call the original, which is impressive. Took a few iterations and had to be adapted to WinDevLib API signatures, but it worked.
Supports both 32bit and 64bit.
Project on GitHub: https://github.com/fafalone/APIHook
Changelog
Here are the updates from the past week. You can also find this information by visiting the GitHub twinBASIC Releases page.
AI-Generated Changelog Summary
* Auto-generated via Claude-Sonnet-4.5, sorted in order of its opinion of "most impactful changes."
-
Chromium Embedded Framework (CEF) support added — A new CEF package and sample project are now available (mirroring the existing WebView2 sample), including an on-demand
CEFBrowser.Initialize()method for loading the browser control programmatically. See the documentation wiki for details. -
VB6 compatibility improvements —
Label.AutoSizenow correctly respectsAlignmentandVerticalAlignmentsettings (fixingvbCenter/vbRightJustifysupport),Form.Clsno longer incorrectly firesForm_Paint, and having a UDT named the same as a Module is now a warning rather than an error, all matching VB6/VBA behaviour. -
IDE quality-of-life enhancements — When a build fails due to a locked output file, the IDE now lists processes holding the lock. The new project dialog gains a Recents (VB6) tab for quickly reopening VB6 projects, and the FIND/REPLACE dialog no longer resets scope unexpectedly while navigating code.
-
Intellisense and code editor fixes — Hovering over underscored identifiers no longer causes erratic tooltip pop-ups (hardened encoding for intellisense/signatures), slow-clicking an intellisense entry is now reliable, and CAPSLOCK no longer accidentally triggers intellisense in Modern mode.
-
Putstatement now supports long strings — A bug preventingPutfrom handling strings longer than 65,534 characters has been resolved. -
Block comments made more flexible — Extra leading whitespace is now accepted before block comment markers, allowing developers to align them consistently within source code.
WARNING: The following issues are present in each of the releases below:
- IMPORTANT: This is a BETA release under active development. It is not recommended for production use.
BETA 980
- improved: (IDE) when a build fails due to a file write error (e.g. the output file is locked), the IDE now attempts to list any running processes that are holding a lock on the output file
- improved: (IDE) Clicking a launched process in the IDE status bar now displays its full command-line string
- improved: (IDE) when applicable, the IDE new project dialog now includes a "Recents (VB6)" tab to show recently opened projects from VB6
- added: Chromium Embedded Framework project support (via package and sample) [ commissioned work ]
- added: Sample 1b. Chromium Embedded Framework Examples (mirroring the 1a. WebView2 sample)
- see: https://github.com/twinbasic/documentation/wiki/Chromium-Embedded-Framework-(CEF)-Packages-(BETA-980)
- fixed: (IDE) CTRL+F find dialog leaves the code hints visible in the code editor when Code Hints Always Visible property is set to OFF [ Krool, discord ]
- fixed: (IDE) rendering glitch in the PROPERTIES panel when a long text value appears in a combo box
- fixed: (IDE) height of property sheet rows in the PROPERTIES panel was not taking into account of custom IDE font sizes
- fixed: (regression, IDE) enter key in the "Manage Keyboard Shortcuts" JSON editor was not working
- fixed: ToolTipText bubble center positioning now reflects the right most cursor position, to match VB6 [ Krool, discord ]
- improved: ToolTipText bubble padding is now dpi-aware
- fixed: Put statement did not support strings longer than 65534 characters in length [ Don, discord ]
- fixed: (IDE) FIND/REPLACE dialog will no longer keep resetting to File scope when navigating the source code [ Don, discord ]
- updated: VBCCR new project to use latest package v1.8.0.96
- fixed: ComboBox.List property let would not preserve ItemData during replacement [ Kimpos, discord ]
- fixed: sample 20 should not ask to add a reference to the Common Controls package, as it is implicitly required [ fafalone, discord ]
- improved: block comments now accept extra spacing preceding them, to allow for custom aligning in source code [ fafalone, discord ]
- fixed: some edge cases around block comments not being syntax highlighted correctly [ FullValueRider, discord ]
- fixed: native Slider control was not auto-clamping the SelStart value between Min and Max when SelectRange is off [ Jim Mack, discord ]
- improved: (IDE) disabled HTML overscrolling for the whole IDE
- improved: hardening of encoding for intellisense/signatures [#2344]
- fixed: (regression) MultiFrame control has been broken for a while
- fixed: (IDE) slow clicking on an intellisense entry would often be ineffective
- fixed: (IDE) CAPSLOCK key no longer triggers intellisense in MODERN intellisense mode
- fixed: Label.AutoSize = True now also takes into account of Label.Alignment (and VerticalAlignment) as per VBx [#2334]
BETA 981
- fixed: Form.Cls should not raise Form_Paint event [ Tecman, discord ]
- fixed: having a UDT named the same as a Module is no longer an error to match VBx (downgraded to a warning) [ DrBobby, discord ]
- fixed: Codegen Model SMALL was broken for built DLLs [ Jim Mack, discord ]
- fixed: tweaks to Format Document / Format Selection to fix some edge cases [ Jim Mack, discord ]
- fixed: setting ComboBox.List(X) property could cause CmoboBox.Click event to fire incorrectly [ kimpos, discord ]
- added: CEFBrowser.CreateInitialized property (defaults TRUE) along with an explicit CEFBrowser.Initialize() method for loading the CEF control on-demand [ Saturnian, discord ]
BETA 982
- fixed: (regression in BETA 981) symbol resolution of conflicting types sometimes incorrect [ FullValueRider, discord ]