Skip to content
Imranosoft

WebView2 browser control for Windows · VBA · VB6 · Access · Excel

LiteView2 Cookbook

21learning chapters in Part I, start to finish
2deployment models in one engine — Registered ActiveX, Registration-Free pool
350+members documented with copy-pasteable VBA
63Registered-mode events, plus the Reg-Free callback model
890+code samples
m_lv LiteView2Lib.LiteView2Ctrl
https://lv2.example/index.html

Customer Dashboard

Status: Hello from VBA!

m_lv.AddHostObjectToScript "vba", Mem_lv.ExecuteScript "...status..."

LiteView2 is a WebView2-based ActiveX/COM control for VBA, VB6, Microsoft Access and Excel. It embeds a real Edge/Chromium browser inside a form, and lets your VBA code and the page's JavaScript call each other directly — in either a Registered ActiveX deployment or a Registration-Free pool.

This Cookbook has three parts:

New to LiteView2? Start with LiteView2 in 5 Minutes.

Contents

Part I — Learn LiteView2

  1. Chapter 1: LiteView2 in 5 Minutes
  2. Chapter 2: Your First Real LiteView2 Screen
  3. Chapter 3: Loading Web Pages and Local Application UI
  4. Chapter 4: Calling JavaScript From VBA
  5. Chapter 5: Calling VBA From JavaScript
  6. Chapter 6: Sending Messages Between VBA and the Page
  7. Chapter 7: Reading and Changing the Web Page From VBA
  8. Chapter 8: Moving Business Data Between VBA and JavaScript
  9. Chapter 9: JSON Without Hand-Written VBA Parsing
  10. Chapter 10: The Higher-Level Two-Way Script Bridge
  11. Chapter 11: Navigation, Browser UI and User Experience
  12. Chapter 12: Downloads, Cookies and Session Data
  13. Chapter 13: Printing, PDF and Capture
  14. Chapter 14: Authentication and Custom Web Requests
  15. Chapter 15: Multiple Browsers, Profiles and Sessions
  16. Chapter 16: Building a Real Access/VBA/VB6 LiteView2 Screen
  17. Chapter 17: Registration-Free Deployment
  18. Chapter 18: Browser Automation Helpers
  19. Chapter 19: Advanced Browser Control and DevTools
  20. Chapter 20: Performance, Diagnostics and Safe Lifecycle
  21. Chapter 21: Licensing and Trial

Part II — Complete API Reference

Part III — Troubleshooting and Limits

Part I

Learn LiteView2

Chapter 1: LiteView2 in 5 Minutes

LiteView2 puts a real web browser (WebView2, the same engine behind modern Edge) inside a VBA form, and lets your VBA code and the page's JavaScript call each other directly. This chapter builds the smallest complete example of that: an Access form that shows a local HTML page, pushes text into that page from VBA, and receives a callback from the page's JavaScript. By the end you will have both directions working.

What you're building

A form named frmCustomerDashboard with a LiteView2Ctrl ActiveX control on it, showing a local HTML page called index.html. The page has one button. Clicking it calls into VBA; VBA responds by rewriting a line of text on the page.

Step 1: Add the control and get a typed reference

Drop a LiteView2Ctrl ActiveX control on the form (its default name is LiteView2Ctrl1), then go to Tools → References and check "LiteView2 1.0 Type Library". In the form's code module:

VBA
Option Explicit
Private m_lv As LiteView2Lib.LiteView2Ctrl

Private Sub Form_Load()
    Set m_lv = Me.LiteView2Ctrl1.Object
End Sub

Me.LiteView2Ctrl1.Object gives you a typed reference to the control that IntelliSense understands from here on.

Note

LiteView2 runs on an automatic trial with no license key required for anything in this chapter. Chapter 21 covers activation for production use.

Step 2: Wait for WebViewReady

Form_Load above only grabs the reference — it doesn't navigate anywhere. That's deliberate: the underlying browser isn't ready the instant the control is created. Add a handler for the control's WebViewReady event:

VBA
Private Sub LiteView2Ctrl1_WebViewReady()

End Sub

Caution

Everything that talks to the page — SetLocalContentRoot, Navigate, AddHostObjectToScript, and the rest — belongs inside WebViewReady (or later), never in Form_Load. Form_Load only guarantees you have a control reference, not a working browser. Two calls belong in Form_Load, after EnsureLicensed: EnableLvFacade and AddScriptToExecuteOnDocumentCreated. Before the browser exists they are queued and applied before the first page. Inside WebViewReady they fail at once with &H80040203.

Step 3: Map a local folder and navigate

SetLocalContentRoot maps a real folder on disk to a virtual hostname, lv2.example. Navigate then loads a page from that virtual host by URL:

VBA
Private Sub LiteView2Ctrl1_WebViewReady()
    m_lv.SetLocalContentRoot CurrentProject.Path & "\html"
    m_lv.Navigate "https://lv2.example/index.html"
End Sub

This expects an html subfolder next to your database, containing index.html.

See Part II → Content & Navigation for the full set of navigation options.

Step 4: The local HTML page

Save this as html\index.html in your Access project folder:

HTML
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Customer Dashboard</title>
</head>
<body>
  <h1>Customer Dashboard</h1>
  <p id="status">Waiting for VBA...</p>
  <button onclick="notifyVBA()">Tell VBA hello</button>

  <script>
    // "vba" matches the first argument of AddHostObjectToScript in VBA.
    // Calling sync.vba.<name>() invokes a Public Sub on the VBA form.
    function notifyVBA() {
      try {
        window.chrome.webview.hostObjects.sync.vba.OnReady();
      } catch (e) {
        document.getElementById('status').textContent = 'Bridge error: ' + e.message;
      }
    }
  </script>
</body>
</html>

Run the form now (with just Steps 1-3 wired up) and you should see the "Customer Dashboard" heading and the "Waiting for VBA..." line. The button won't do anything yet — Step 6 wires it up. First, VBA needs a way to change what's on screen.

Step 5: Push content from VBA into the page

ExecuteScript runs a line of JavaScript inside the page and hands back the result as a JSON-encoded string. You can call it from ordinary code (a button, a timer) or from NavigationCompleted once the page has loaded. Do not call it inside WebViewReady, or inside a method the page is calling (Step 6): there it fails at once with error &H80040203. This one-line call reaches into the page and rewrites the status text:

VBA
m_lv.ExecuteScript "document.getElementById('status').textContent = 'Hello from VBA!';"

We're calling it as a statement and ignoring the return value here, since we only care about the side effect on the page. (If you did capture the return value — say, from m_lv.ExecuteScript("document.title") — you'd get back "Customer Dashboard", quotes included, because the result is always JSON-encoded.)

In our example the page calls VBA when the button is clicked (Step 6). Inside such a call the page is waiting for VBA, so a synchronous ExecuteScript is refused there. Step 6 therefore sends the same line with ExecuteScriptAsync, which queues it and returns at once.

See Part II → Scripting & Data Exchange for ExecuteScript with functions, arguments, and structured return data.

Step 6: Let the page call back into VBA

Now the other direction: let JavaScript call VBA. Two lines make that possible — AreHostObjectsAllowed = True, and AddHostObjectToScript "vba", Me, which registers the form itself (Me) as a COM object the page can reach under the name "vba". Host objects only bind on the next navigation, so they must be registered before Navigate runs — add them to WebViewReady in this order (map the content root, then register the host object, then navigate):

VBA
Private Sub LiteView2Ctrl1_WebViewReady()
    m_lv.SetLocalContentRoot CurrentProject.Path & "\html"
    m_lv.AreHostObjectsAllowed = True
    m_lv.AddHostObjectToScript "vba", Me

    m_lv.Navigate "https://lv2.example/index.html"
End Sub

On the page side, the button's notifyVBA() function (Step 4) already calls window.chrome.webview.hostObjects.sync.vba.OnReady(). "vba" is the name we just registered, and OnReady must be a Public Sub on the form:

VBA
Public Sub OnReady()
    m_lv.ExecuteScriptAsync "document.getElementById('status').textContent = 'Hello from VBA!';"
End Sub

That's the Step 5 line, sent with ExecuteScriptAsync: VBA is answering a call from the page, and ExecuteScript would fail there with &H80040203. It now runs every time the page tells VBA the button was clicked.

See Part II → Host Objects & the JavaScript Bridge for exposing more than one method, passing arguments, and returning values back to JavaScript.

Put it together

The complete form module:

VBA
Option Explicit
Private m_lv As LiteView2Lib.LiteView2Ctrl

Private Sub Form_Load()
    Set m_lv = Me.LiteView2Ctrl1.Object
End Sub

Private Sub LiteView2Ctrl1_WebViewReady()
    m_lv.SetLocalContentRoot CurrentProject.Path & "\html"
    m_lv.AreHostObjectsAllowed = True
    m_lv.AddHostObjectToScript "vba", Me

    m_lv.Navigate "https://lv2.example/index.html"
End Sub

Public Sub OnReady()
    m_lv.ExecuteScriptAsync "document.getElementById('status').textContent = 'Hello from VBA!';"
End Sub

Together with html\index.html from Step 4, that's the whole example.

Run it

Open frmCustomerDashboard. The page loads showing "Customer Dashboard" and "Waiting for VBA...". Click Tell VBA hello. The status line changes to "Hello from VBA!". Under the hood: the button's JavaScript called vba.OnReady() across the bridge, VBA's OnReady ran and sent the line with ExecuteScriptAsync; the page applies it as soon as OnReady returns.

You now have a local HTML page running inside an Access form, with VBA and JavaScript each able to call the other.

Registration-Free deployment skips the ActiveX control and drives the same browser through a pool object instead of m_lv; Chapter 17 covers that deployment model.

Chapter 2: Your First Real LiteView2 Screen

Chapter 1 got a LiteView2 control on a form and something on screen. This chapter turns that into a form you could actually ship: a typed reference so the VBA editor gives you IntelliSense, license activation in the right place, the ready-event ordering that real pages depend on, and a shutdown routine that doesn't leave anything behind.

The running example for this chapter is frmCustomerDashboard — an Access form with a LiteView2Ctrl1 control that loads a local HTML page, lets the user edit a customer's notes, and saves them back through VBA. Everything here is Registered Mode (the ActiveX control dropped straight onto the form). Registration-Free deployment uses the pool equivalent of every call shown in this chapter; Chapter 17 covers that model in full.

Get a typed reference, not Me.LiteView2Ctrl1

Type Me.LiteView2Ctrl1. in the VBA editor and Access's autocomplete shows you Name, Top, Left, Visible — the generic properties every ActiveX control has. It does not show Navigate, ActivateLicense, SetLocalContentRoot, or any of LiteView2's other members. This isn't a LiteView2 limitation — Access wraps every ActiveX control dropped on a form in a generic Control object. At runtime that wrapper forwards your calls to the real control through IDispatch::Invoke, but its type information doesn't include the control's actual members, so the editor has nothing to show you. The legacy WebBrowser control and the Microsoft DatePicker control have the exact same gap.

The fix is a module-level variable typed as the real control class, populated from .Object:

VBA
Option Explicit

' Typed reference — gives IntelliSense everywhere it's used.
Private m_lv As LiteView2Lib.LiteView2Ctrl

Private Sub Form_Load()
    ' .Object peels off Access's generic wrapper and returns the underlying
    ' ActiveX object, which is what the LiteView2Ctrl type expects. Without
    ' .Object the assignment raises "Type mismatch" — Access's wrapper is
    ' not QueryInterface-compatible with the LiteView2Ctrl coclass.
    Set m_lv = Me.LiteView2Ctrl1.Object
End Sub

From this point on, m_lv. gives full IntelliSense — every method, property, and enum in the LiteView2 type library.

One-time setup, once per Access project:

  1. In the VBA editor, Tools → References…
  2. Find LiteView2 1.0 Type Library in the list and check the box.
  3. Click OK. If LiteView2 isn't in the list, the OCX isn't registered on this machine. Run LiteView2 Setup (liteview2-setup.zip from https://www.imranosoft.com/products/liteview2/#downloads); it installs and registers both the 32-bit and the 64-bit control. Setup can safely migrate earlier customer releases that were installed manually with regsvr32. For Registration-Free deployment there is nothing to register: put LiteView2_x64.ocx and LiteView2_x86.ocx beside the database or workbook (liteview2-regfree.zip); Chapter 17 covers that model.
  4. Optional: Debug → Compile to force VBA to re-resolve types immediately rather than at next run.

Late-bound still works without this. If you're distributing a database to users who may not have set up references, Private m_lv As Object instead of Private m_lv As LiteView2Lib.LiteView2Ctrl runs exactly the same way — m_lv.Navigate "..." still resolves through IDispatch::Invoke at runtime. You only lose IntelliSense while writing the code; nothing breaks for the end user.

Form_Load does less than you'd expect

The control's WebView2 engine starts up asynchronously — it isn't ready the instant the control is created, even though Form_Load has already run by then. Code that touches the page or the browser session before it's ready either does nothing, races the initialization, or leaves a stuck license watermark. So the rule is a hard split:

VBA
' ❌ WRONG — WebView2 isn't ready yet when Form_Load runs.
Private Sub Form_Load()
    Set m_lv = Me.LiteView2Ctrl1.Object
    m_lv.SetLocalContentRoot CurrentProject.Path        ' too early
    m_lv.AddHostObjectToScript "vba", Me                ' too early
    m_lv.Navigate "https://lv2.example/index.html"      ' too early
End Sub
VBA
' ✅ CORRECT — Form_Load only gets the reference and activates the license.
Private Sub Form_Load()
    Set m_lv = Me.LiteView2Ctrl1.Object
    EnsureLicensed m_lv
End Sub

Private Sub LiteView2Ctrl1_WebViewReady()
    m_lv.SetLocalContentRoot CurrentProject.Path
    m_lv.AreHostObjectsAllowed = True
    m_lv.AddHostObjectToScript "vba", Me
    m_lv.Navigate "https://lv2.example/customer_dashboard.html"
End Sub

License activation: one shared module, called from Form_Load

Put the activation key in exactly one place — a shared module, never in per-form code — so rotating the key later means editing one file instead of every form in the database. Create a new standard module named modLV2License:

VBA
' ===== modLV2License — START =================================================
Option Explicit

' Edit LV2_COMPANY and LV2_KEY ONCE here. Forms call EnsureLicensed.
' Leave LV2_KEY empty to keep the 30-day Trial Period.
Private Const LV2_COMPANY As String = "Your Company"
Private Const LV2_KEY     As String = ""    ' "V1|..."

Private m_activated As Boolean

' Activate the runtime license against any LiteView2 control instance.
' Safe to call from every form's Form_Load — only the first call does
' the work; later calls are a no-op. Activation is process-wide.
Public Sub EnsureLicensed(ByVal ctrl As Object)
    If m_activated Then Exit Sub
    If ctrl Is Nothing Then Exit Sub
    If Len(LV2_KEY) = 0 Then Exit Sub
    ctrl.ActivateLicense LV2_COMPANY, LV2_KEY
    m_activated = True
End Sub
' ===== modLV2License — END ===================================================

Every form calls EnsureLicensed m_lv in Form_Load — before the first Navigate, never from WebViewReady. By the time WebViewReady fires, the control has already used the license state to decide how to navigate, and activating after Navigate risks leaving a trial watermark already rendered on the page. EnsureLicensed is idempotent — it checks its own flag — so calling it from every form's Form_Load is safe; only the first call in the process does anything. Full licensing detail — trial behavior, key formats, what happens if activation fails — is Chapter 21.

Ordering inside WebViewReady: content root, then host objects, then Navigate

Inside the ready handler, order matters: SetLocalContentRoot first, then AreHostObjectsAllowed / AddHostObjectToScript, then Navigate last. Any host object you want the page to call must be registered before the Navigate that loads the page which calls it — a page can only reach host objects that already existed at load time.

The canonical per-form template

This is the full pattern the rest of Part I builds on. Everything above is assembled here in one place.

VBA
' ============================================================================
'  Registered Mode — canonical lifecycle template (per form)
' ============================================================================
'  Form prerequisite:
'    - A LiteView2Ctrl ActiveX named  LiteView2Ctrl1  (Access's default name)
'
'  Project prerequisites:
'    - modLV2License module added to the project (holds the activation key)
'    - Tools -> References -> check "LiteView2 1.0 Type Library"
'
'  Lifecycle rules this template follows:
'    1. Form_Load: the typed reference, EnsureLicensed, and (if you use
'       them) EnableLvFacade / AddScriptToExecuteOnDocumentCreated —
'       queued until the browser is ready.
'    2. SetLocalContentRoot, host objects, and the first Navigate go in
'       the WebViewReady event.
'    3. Host objects must be added BEFORE the Navigate that uses them.
'    4. Set m_lv = Nothing in Form_Close. No explicit teardown needed.
'
'  When you add buttons that the user may click while focus is inside the
'  browser, mirror Click into MouseDown — see the button-click section
'  below.
' ============================================================================
Option Compare Database
Option Explicit

' Typed reference. The "As LiteView2Lib.LiteView2Ctrl" gives IntelliSense
' on every m_lv.* call. ".Object" in Form_Load below peels Access's wrapper
' so the assignment is type-compatible; without it, Set raises Type mismatch.
Private m_lv As LiteView2Lib.LiteView2Ctrl

Private Sub Form_Load()
    On Error GoTo ErrH

    Set m_lv = Me.LiteView2Ctrl1.Object

    ' Single call -- activation key lives in modLV2License.bas.
    ' Safe to call from every form: only the first call does real work.
    EnsureLicensed m_lv

    Exit Sub
ErrH:
    MsgBox "Form_Load: " & Err.Number & " " & Err.Description, vbCritical
End Sub

Private Sub LiteView2Ctrl1_WebViewReady()
    On Error GoTo ErrH

    ' Order matters: content root first, then host objects, then Navigate.
    m_lv.SetLocalContentRoot CurrentProject.Path
    m_lv.AreHostObjectsAllowed = True
    m_lv.AddHostObjectToScript "vba", Me
    m_lv.Navigate "https://lv2.example/customer_dashboard.html"

    Exit Sub
ErrH:
    MsgBox "WebViewReady: " & Err.Number & " " & Err.Description, vbCritical
End Sub

' Called by the page via window.chrome.webview.hostObjects.sync.vba.OnReady()
' This runs INSIDE the page's call: the page waits until it returns. Calls that
' wait for the browser (ExecuteScript, GetCookies, CallScriptSync, ...) fail here
' at once with &H80040203. Note that the page is ready, or push data with
' ExecuteScriptAsync, and return. Post-load work that needs ExecuteScript belongs
' in LiteView2Ctrl1_NavigationCompleted, which runs after WebView2's callback.
Public Sub OnReady()
    ' Page is ready. Push the customer's notes with ExecuteScriptAsync, e.g.
    ' m_lv.ExecuteScriptAsync "loadNotes(" & notesJson & ");"
    ' (ExecuteScript would fail here with &H80040203: the page is waiting for this call.)
End Sub

' Called by the page's saveContent() via the same "vba" host object.
Public Sub SaveCustomer(ByVal CustomerName As String, ByVal Notes As String)
    ' TODO: write CustomerName / Notes back to tblCustomers.
End Sub

Private Sub Form_Close()
    On Error Resume Next
    If Not m_lv Is Nothing Then
        m_lv.Stop                  ' halt any in-flight navigation before teardown
        Set m_lv = Nothing         ' release the reference; Access destroys the control next
    End If
End Sub

What should happen: open frmCustomerDashboard in Access and the LiteView2 control area is blank for a moment while the browser engine starts, then customer_dashboard.html loads and renders. Nothing you typed in Form_Load or WebViewReady throws an error, the page can call back into OnReady, and closing the form leaves no error dialogs and no lingering process.

The page side: customer_dashboard.html

The smallest page that exercises the round trip — it announces itself ready, and exposes a saveContent() function that VBA triggers via ExecuteScriptAsync:

HTML
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"></head>
<body>
  <input id="txtName" placeholder="Customer name">
  <textarea id="txtNotes" placeholder="Notes"></textarea>
  <div id="divResults"></div>

  <script>
    function saveContent() {
      const name = document.getElementById('txtName').value;
      const notes = document.getElementById('txtNotes').value;
      window.chrome.webview.hostObjects.sync.vba.SaveCustomer(name, notes);
      document.getElementById('divResults').textContent = 'Saved.';
    }

    window.addEventListener('DOMContentLoaded', () => {
      window.chrome.webview.hostObjects.sync.vba.OnReady();
    });
  </script>
</body>
</html>

OnReady fires on page load through the vba host object registered in WebViewReady; SaveCustomer fires later, whenever the Access side calls m_lv.ExecuteScriptAsync "saveContent()" — see the button pattern next.

Closing the form safely

Form_Close above does two things and swallows errors on purpose:

Button clicks: the first-click-does-nothing caveat

Access moves keyboard focus to a button on the first click when focus was previously inside an embedded ActiveX control — the LiteView2 control, the legacy WebBrowser control, Microsoft DatePicker, all of them. On that first click, the button's Click event does not fire at all; the user has to click a second time before anything happens. This is long-standing Access behavior, not something LiteView2 does.

In practice: a user types into the page inside LiteView2, clicks a "Save" button on the Access form — nothing happens. They click again, and the save runs. Customers report this as "the button only works on the second click."

The fix is to mirror Click into MouseDown. MouseDown fires the instant the mouse button goes down regardless of focus state, so the action runs on the first physical click. Keep Click too, so keyboard activation (Enter / Spacebar) still works:

VBA
Private Sub cmdSave_Click()
    DoSave  ' the actual work
End Sub

Private Sub cmdSave_MouseDown(Button As Integer, Shift As Integer, _
                              X As Single, Y As Single)
    If Button = 1 Then DoSave  ' left mouse button only
End Sub

Private Sub DoSave()
    If m_lv Is Nothing Then Exit Sub
    m_lv.ExecuteScriptAsync "saveContent()"
End Sub

Apply this pattern to any form button the user might click while focus is inside the LiteView2 control. Buttons triggered only from VBA code (for example cmdSave.Value = True) don't need it.

See Part II → Lifecycle & Teardown for the full Registered-vs-Reg-Free timeline comparison, and Part II → Licensing for every ActivateLicense edge case (failed activation, trial expiry behavior, multi-form timing).

Chapter 3: Loading Web Pages and Local Application UI

Every recipe in this chapter answers the same underlying question: how do you get content into the LiteView2 control? There are three sources — a local file on disk, a remote URL, and an HTML string you build yourself in VBA — and a handful of methods for moving between pages once something is loaded.

The examples below assume m_lv is already a valid, initialized LiteView2Lib.LiteView2Ctrl reference on your form, as set up in Chapter 2. Registration-Free mode reaches the same operations through a pool object instead of a control reference — pool (As Object, from GetPool()) and idx (As Long, the browser index) in place of m_lv. Chapter 17 covers that deployment model in full; this chapter stays in Registered mode and flags the handful of places where the Reg-Free call shape genuinely differs.

3.1 Three ways to load content

The rest of this chapter works through each of these as a concrete scenario.

3.2 Scenario: displaying a local dashboard

Say your Access application ships an html subfolder next to the database, containing a small dashboard that summarizes today's orders. SetLocalContentRoot maps a folder to the fixed virtual hostname https://lv2.example/; you then Navigate to a file under it.

VBA
Private Sub LiteView2Ctrl1_WebViewReady()
    m_lv.SetLocalContentRoot CurrentProject.Path & "\html"
    m_lv.Navigate "https://lv2.example/dashboard.html"
End Sub

As established in Chapter 2, this belongs in WebViewReady, not Form_Load — Form_Load only guarantees a control reference, not a working browser.

CurrentProject.Path & "\html" becomes the URL root, so a file at ...\html\dashboard.html on disk is reached at https://lv2.example/dashboard.html — there is no /html/ segment in the URL, because the html folder itself is the root once mapped.

A minimal dashboard.html to go with it:

HTML
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>Order Dashboard</title></head>
<body>
  <h1>Today's Orders</h1>
  <div id="divResults-2">Loading…</div>
</body>
</html>

What should happen: the control shows dashboard.html, and m_lv.DocumentTitle reads "Order Dashboard" once the page finishes loading.

The path-mapping table

The one detail worth internalizing here is that the mapping is one-to-one: whatever folder you pass to SetLocalContentRoot becomes the URL root, full stop.

Disk path you passURL rootExample file on diskURL to navigate to
C:\Apps\MyDB\https://lv2.example/C:\Apps\MyDB\index.htmlhttps://lv2.example/index.html
C:\Apps\MyDB\https://lv2.example/C:\Apps\MyDB\pages\admin.htmlhttps://lv2.example/pages/admin.html
CurrentProject.Pathhttps://lv2.example/any file in that folderhttps://lv2.example/<file>

Common path-mapping mistakes

Caution

all four mistakes above produce the same symptom — a blank control or a browser error page — with no LiteView2-specific error to point you at the cause. When a local page won't load, check the mapping and the file path before anything else.

Registration-Free has the same call on the pool — pool.SetLocalContentRoot idx, folder — with idx as the leading browser-index argument. Chapter 17 covers the pool workflow in full.

See Part II → Navigation for NavigateToLocalFile, a shorthand for navigating to a file already under your SetLocalContentRoot mapping without building the https://lv2.example/... URL yourself — you still call SetLocalContentRoot first (mentioned again in §3.9).

3.3 Scenario: displaying a local form and switching between pages

A multi-screen local UI is just more files under the same mapped root, with Navigate called again each time the user moves to a different screen. Extend the dashboard example with a Customers screen and an Orders screen in the same html folder:

VBA
Private Sub cmdCustomers_Click()
    m_lv.Navigate "https://lv2.example/customers.html"
End Sub

Private Sub cmdOrders_Click()
    m_lv.Navigate "https://lv2.example/orders.html"
End Sub

Because customers.html and orders.html sit under the same root you mapped in WebViewReady, no re-mapping is needed — Navigate alone moves between them. Navigate doesn't care whether the target is local or remote; it's the same call either way, which is what makes switching between a local screen and a remote one (§3.4) a one-line change.

See Part II → Navigation for the full Navigate signature.

3.4 Scenario: opening a remote business application

To load a hosted application — a CRM, an internal reporting portal — Navigate an https:// URL directly. No content-root mapping applies to remote addresses; that mechanism only exists to give local files an https://-shaped address to be loaded from.

VBA
Private Sub cmdOpenCRM_Click()
    m_lv.Navigate "https://crm.mycompany.com/dashboard"
End Sub

What should happen: the control requests the remote page over the network and renders whatever it returns, exactly as a browser tab would.

3.5 A custom hostname: SetVirtualHostNameToFolderMapping

SetLocalContentRoot always maps to the fixed hostname lv2.example. If you want your own hostname instead — for example to keep a second, independent content area (say, exported report files) separate from your main app's lv2.example mapping — call SetVirtualHostNameToFolderMapping directly:

VBA
m_lv.SetVirtualHostNameToFolderMapping "myapp.local", _
    CurrentProject.Path & "\reports", 1
m_lv.Navigate "https://myapp.local/quarterly-summary.html"

The folder-to-URL mapping rules and the same four common mistakes from §3.2 apply here too — only the hostname changes. To remove a mapping later, ClearVirtualHostNameToFolderMapping exists (mentioned in §3.9; not demoed here).

Reg-Free:

VBA
pool.SetVirtualHostNameToFolderMapping idx, "myapp.local", _
    CurrentProject.Path & "\reports", 1
pool.Navigate idx, "https://myapp.local/quarterly-summary.html"

See Part II → Navigation for the meaning of the trailing 1 parameter and the rest of the signature.

3.6 Building a page directly from VBA: NavigateToString

Sometimes there's no HTML file at all — you want to generate a report on the fly from data already in your Access database and show it in the control without writing anything to disk. NavigateToString takes an HTML string and loads it directly.

VBA
Private Sub ShowOrderReport(customerID As Long)
    ' Call from a command button's Click event, e.g.:
    '   Private Sub cmdShowOrderReport_Click()
    '       ShowOrderReport Me.txtCustomerID.Value
    '   End Sub
    Dim rs As DAO.Recordset
    Dim html As String

    Set rs = CurrentDb.OpenRecordset( _
        "SELECT OrderID, OrderDate, Total FROM tblOrders " & _
        "WHERE CustomerID = " & customerID)

    html = "<html><body><h1>Order Report</h1><table border=""1"">" & _
           "<tr><th>Order ID</th><th>Date</th><th>Total</th></tr>"

    Do While Not rs.EOF
        html = html & "<tr><td>" & rs!OrderID & "</td><td>" & _
               rs!OrderDate & "</td><td>" & rs!Total & "</td></tr>"
        rs.MoveNext
    Loop

    html = html & "</table></body></html>"
    rs.Close

    m_lv.NavigateToString html
End Sub

What should happen: the control immediately shows a formatted table of that customer's orders, built entirely in memory — no dashboard.html-style file, and no SetLocalContentRoot call needed for this particular screen.

Reg-Free: pool.NavigateToString idx, html — same string, same shape, no meaningful difference beyond the pool/idx pattern already noted.

See Part II → Navigation for NavigateToStringSync, the blocking variant (mentioned in §3.9).

3.7 Back, forward, refresh, stop

Once a user has moved through a few pages — local or remote — the usual browser-style navigation controls are available: GoBack, GoForward, Refresh, Stop. GoBack and GoForward should be guarded by their corresponding CanGoBack / CanGoForward checks, since there may be nothing to go back or forward to.

VBA
Private Sub cmdBack_Click()
    If m_lv.CanGoBack Then m_lv.GoBack
End Sub

Private Sub cmdForward_Click()
    If m_lv.CanGoForward Then m_lv.GoForward
End Sub

Private Sub cmdRefresh_Click()
    m_lv.Refresh
End Sub

Private Sub cmdStop_Click()
    m_lv.Stop
End Sub

Caution

always check CanGoBack / CanGoForward before calling GoBack / GoForward. There's no history to go back to on the first page a user visits, or forward to until they've gone back at least once.

Reg-Free: the same four calls, indexed — pool.CanGoBack(idx), pool.GoBack idx, pool.Refresh idx, pool.Stop idx.

See Part II → Navigation for full details.

3.8 Reading navigation state: Url, DocumentTitle, IsLoading

Three read-oriented properties round out this chapter — useful for a status bar, a window caption, or a simple loading indicator.

VBA
' Update a status label and the form caption after navigating
lblStatus.Caption = "Viewing: " & m_lv.Url
Me.Caption = "MyApp — " & m_lv.DocumentTitle

' Check whether a page is still loading
If m_lv.IsLoading Then
    Debug.Print "Still loading..."
End If

Url is also a settable property in Registered mode — m_lv.Url = "https://example.com" navigates, the same as calling Navigate. DocumentTitle and IsLoading are read-only.

Reg-Free: pool.GetUrl(idx), pool.GetTitle(idx), and pool.IsLoading(idx) read the same three values. There is no Url property setter in the pool — call pool.Navigate idx, url instead of assigning to it.

See Part II → Navigation for the complete property list.

3.9 Other navigation methods you'll meet later

A few more navigation members exist in the API beyond what this chapter demos. They're worth knowing by name now; Part II → Navigation covers their full parameters and behavior:

Custom navigation with a specific HTTP method, POST body, or headers — NavigateWithWebResourceRequest, CreateWebResourceRequest, NavigateWithCustomRequest, and related members — also exists, but it's tied up with authentication scenarios and is covered in full in Chapter 14 (Authentication and Custom Web Requests) rather than here.

Chapter 4: Calling JavaScript From VBA

The LiteView2 control shows a web page, but the page is not just a display surface. Once it is loaded, your VBA code can run JavaScript inside it and read values back out of it. This chapter teaches the four calls that cover almost every real scenario — ExecuteScriptAsync, ExecuteScript, ExecuteScriptWithResult, and ExecuteScriptWithArgs — plus brief pointers to a handful of more specialized members. Part II → Script Execution has the complete, exhaustive reference for all of them.

All examples assume a form-level control declared and already navigated to a page:

VBA
Dim m_lv As LiteView2Lib.LiteView2Ctrl

The running example is a Customers dashboard page, dashboard.html, loaded into m_lv. It has a status line, two KPI counters, a small form, and a placeholder chart object:

HTML
<!-- dashboard.html (excerpt) -->
<div id="divResults-3"></div>
<div id="kpiCustomers">0</div>
<div id="kpiOrders">0</div>

<input id="txtName-2" value="John Doe" />
<input id="txtEmail" value="john@example.com" />

<script>
  function updateStatus(msg) {
    document.getElementById('divResults').textContent = msg;
  }

  function loadKpis(customerCount, orderCount) {
    document.getElementById('kpiCustomers').textContent = customerCount;
    document.getElementById('kpiOrders').textContent = orderCount;
  }

  function getFormData() {
    return {
      name: document.getElementById('txtName').value,
      email: document.getElementById('txtEmail').value
    };
  }

  window.myChart = {
    update: function (data) {
      console.log('chart updated with', data);
    }
  };
</script>

Every recipe below calls into this same page.

Three tiers of calling into the page

LiteView2 gives you three different ways to run JavaScript, and picking the right one matters:

  1. Fire-and-forget (ExecuteScriptAsync) — you tell the page to do something and do not wait for or care about a result. Cheapest option, use it for anything that just updates the DOM or calls a void function.
  2. Synchronous result (ExecuteScript, ExecuteScriptWithResult) — you run an arbitrary JavaScript expression or statement and get a JSON-encoded string back, optionally with a success flag and an error message if the script threw. They wait for the page's answer, so inside WebViewReady, other inline events and host-object methods they fail at once with &H80040203; see "Getting a result where synchronous calls are refused" below.
  3. Structured helpers (ExecuteScriptWithArgs) — instead of building a JavaScript string yourself, you name a function and let LiteView2 handle the calling convention; VBA values (like Array(100, 50)) are auto-serialized for you. Two more specialized, Registered-mode-only helpers with a similar goal (CallJsFunction, SetJsVariable) exist for a dot-path/JSON-string calling convention — mentioned briefly later in this chapter, covered in full in Part II.

The rest of this chapter works through the four main tools in that order, then briefly names a few more members you'll meet later.

Fire-and-forget: ExecuteScriptAsync

Use this when you want the page to do something and you do not need a result back — updating a status line, toggling a CSS class, calling a void JS function.

VBA
m_lv.ExecuteScriptAsync "updateStatus('Processing...');"
m_lv.ExecuteScriptAsync "document.getElementById('divResults').textContent = 'Updated';"

What happens: the JavaScript runs in the page; your VBA code moves on immediately without waiting for it to finish and without receiving any value back.

Registration-Free uses the pool equivalent — pool.ExecuteScriptAsync idx, script — where pool is the object returned by GetPool() and idx is the browser index; Chapter 17 covers that deployment model.

See Part II → Script Execution for the full member reference.

Getting a result back: ExecuteScript

Use this when you need a value out of the page — reading document.title, calling a function and reading its return value.

VBA
Dim result As String
result = m_lv.ExecuteScript("document.title")
Debug.Print "Title: " & result   ' "My Page Title"

result = m_lv.ExecuteScript("getFormData()")
Debug.Print result   ' {"name":"John Doe","email":"john@example.com"}

What happens: the script runs synchronously and the JavaScript result is returned as a JSON-encoded string. Note the first example: the returned VBA string literally contains the surrounding quote characters, because a JavaScript string is JSON-encoded as a quoted string. If you only want the raw text, strip the quotes yourself or run the result through a JSON parser — LiteView2 hands you the JSON text, not a parsed value.

ExecuteScript waits at most SynchronousTimeOut ms (default 30000; 0 also means 30000). On a timeout it raises &H800705B4 (-2147023436) and sets LastErrorCode; the page may still run the script later. Inside WebViewReady, NavigationStarting, the other inline events and host-object methods it raises &H80040203 at once and runs nothing. Use ExecuteScriptAsync there. It works inside NavigationCompleted, DOMContentLoaded, WebMessageReceived and the other notification events. Before the browser exists it fails: it is not queued (ExecuteScriptAsync is).

Caution

ExecuteScript does not tell you whether the script threw an exception — a failed script and a script that legitimately returns an empty result can be hard to tell apart. If you need to know whether the call actually succeeded, use ExecuteScriptWithResult below.

See Part II → Script Execution for the full member reference.

Getting a result where synchronous calls are refused

ExecuteScript and ExecuteScriptWithResult cannot run inside WebViewReady, NavigationStarting and the other inline events, or inside a VBA method the page is calling: they fail there with &H80040203. If the page is calling you, have it pass the values as arguments. Otherwise send the script with ExecuteScriptAsync and let the page post the answer back:

VBA
' Inside an inline event:
m_lv.ExecuteScriptAsync "chrome.webview.postMessage(JSON.stringify({action:'title', value: document.title}));"

' The answer arrives here a moment later (Registered mode):
Private Sub LiteView2Ctrl1_WebMessageReceived(ByVal message As String, ByVal source As String)
    If m_lv.JsonGetValue(message, "action") = "title" Then Debug.Print m_lv.JsonGetValue(message, "value")
End Sub

In Reg-Free mode the answer goes to the macro you registered with pool.SetWebMessageCallback idx, Application, "MacroName". Everywhere else (buttons, timers, NavigationCompleted, WebMessageReceived) just use ExecuteScript.

Getting a result with error info: ExecuteScriptWithResult

Use this when the script might fail and you need to know about it — instead of just getting a string back, you get a result, a success flag, and an exception message.

VBA
Dim resultJson As String, succeeded As Boolean, errMsg As String
m_lv.ExecuteScriptWithResult "1 + 2", resultJson, succeeded, errMsg
If succeeded Then
    Debug.Print "Result: " & resultJson   ' "3"
Else
    Debug.Print "Error: " & errMsg
End If

What happens: the script runs synchronously; resultJson receives the JSON-encoded result exactly as ExecuteScript would, succeeded tells you whether it ran without throwing, and errMsg carries the exception text when it did not.

ExecuteScriptWithResult waits at most SynchronousTimeOut (0 means 30000). A timeout raises no error. Instead it returns succeeded = False, puts "ExecuteScriptWithResult got no result from the page within … ms (SynchronousTimeOut)…" in errMsg, and sets LastErrorCode = &H800705B4. So succeeded = False does not always mean the script threw. Inside inline events and host-object methods it raises &H80040203 (it does not return succeeded = False) and runs nothing.

See Part II → Script Execution for the full member reference.

Calling a function with VBA values: ExecuteScriptWithArgs

Use this when you want to call a specific JS function with values that already exist as VBA variables, without hand-building a JavaScript call string and worrying about quoting.

VBA
Dim result As String
result = m_lv.ExecuteScriptWithArgs("loadKpis", Array(100, 50))
' Calls loadKpis(100, 50) in the page

What happens: LiteView2 serializes the VBA array of arguments and calls loadKpis with them — loadKpis(100, 50), matching the function signature in dashboard.html. Like ExecuteScript, the returned value is the function's JSON-encoded return value.

See Part II → Script Execution for the full member reference.

A few more script members you'll meet later

A handful of more specialized script members exist beyond the four above. They're worth knowing by name now; Part II → Script Execution covers their full parameters, quote-doubling details, and behavior:

Which one do I use?

NeedUse
Run something and don't care about the resultExecuteScriptAsync
Run an expression/statement and read the resultExecuteScript
Same, but you need to know if it failed and whyExecuteScriptWithResult
Call a known JS function with VBA values as argumentsExecuteScriptWithArgs
Call a function by dotted path with JSON args (Registered only)CallJsFunction
Set a JS variable to a JSON value (Registered only)SetJsVariable
Run setup script on every future page loadAddScriptToExecuteOnDocumentCreated
Turn JavaScript on/off for the browserIsScriptEnabled

Chapter 5: Calling VBA From JavaScript

The previous chapter showed VBA driving the page — calling into JavaScript from your VBA code. This chapter is the other direction: JavaScript running inside the embedded page calling back into a Public method on your VBA code, as if the browser could dial your Access form or class module directly.

This is what makes LiteView2 useful for anything beyond a static display: an HTML page can have a "Save" button, a form, a grid — and the actual work (writing to a table, running a query, updating other controls on your Access form) still happens in VBA, where you already know how to do it. The page just needs a way to ask VBA to do it.

That mechanism is called a host object.

What we're building

A form, frmOrders, hosts a LiteView2 control (m_lv) showing an order-entry page. The page has an order total field and a Save Order button. When the user clicks Save, JavaScript reads the field, calls a VBA method with the order ID and total, VBA writes the row and returns a confirmation string, and JavaScript displays it — all without leaving the page.

The setup: three steps before Navigate

Exposing VBA to JavaScript takes three calls, and they have to happen in your ready handler, in this order, before you call Navigate. In Registered Mode that ready handler is the WebViewReady control event; in Reg-Free Mode it's a callback method you register yourself with SetReadyCallback (commonly named OnBrowserReady in this Cookbook's examples, but any Public Sub name works). These are two different mechanisms — an event versus a named callback you wire up — that play the same conceptual role in each deployment model; Chapter 17 covers the Reg-Free version in full. This chapter stays in Registered Mode, on the same Access form and LiteView2Ctrl1 control used in Chapters 1-4:

VBA
Private Sub LiteView2Ctrl1_WebViewReady()
    m_lv.SetLocalContentRoot CurrentProject.Path & "\html"
    m_lv.AreHostObjectsAllowed = True
    Dim helper As New clsJsBridge
    m_lv.AddHostObjectToScript "vba", helper
    m_lv.Navigate "https://lv2.example/orders.html"
End Sub

Caution

— host objects only bind on the next navigation. AddHostObjectToScript has to run before the Navigate call that loads the page which needs it. If you call it after the page has already loaded — or after some other navigation has already happened — the page you're looking at right now won't see the object; it only takes effect starting with the navigation that follows. This is the third of the three setup rules that trip up most customers, and it's the one specific to host objects: SetLocalContentRoot → AreHostObjectsAllowed → AddHostObjectToScript → Navigate, always in that order, always before the page loads.

If you ever need to swap out or disable the bridge — for example, before re-navigating to a page that shouldn't have VBA access — remove it explicitly:

VBA
m_lv.RemoveHostObjectFromScript "vba"

Registration-Free uses the pool equivalent (pool.RemoveHostObjectFromScript idx, "vba"); Chapter 17 covers that deployment model.

Exposing VBA: what AddHostObjectToScript actually registers

AddHostObjectToScript takes a name (this is the name JavaScript will use to reach it) and a VBA object. Two things can play the role of that object:

Both are legitimate; the example above uses a clsJsBridge instance. If you only need one or two simple callbacks, exposing Me directly and giving the form a Public Sub works just as well — see the sync.vba.OnReady() example later in this chapter, where Me is the exposed object.

Registration-Free uses pool.SetAreHostObjectsAllowed idx, True and pool.AddHostObjectToScript idx, "vba", helper; Chapter 17 covers that deployment model.

AreHostObjectsAllowed is a plain Boolean read/write property — set it True once, before the first AddHostObjectToScript call, as shown above. See Part II → Host Object Bridging for the full property reference and the pool equivalent (GetAreHostObjectsAllowed / SetAreHostObjectsAllowed).

The VBA side: a callable method

VBA
' clsJsBridge (class module)

Public Function SaveOrder(ByVal OrderID As Long, ByVal OrderTotal As Currency) As String
    Dim db As DAO.Database
    Set db = CurrentDb

    db.Execute "UPDATE tblOrders SET OrderTotal = " & OrderTotal & _
               " WHERE OrderID = " & OrderID

    SaveOrder = "Order " & OrderID & " saved: $" & Format(OrderTotal, "0.00")
End Function

Nothing about this method is LiteView2-specific — it's an ordinary Public Function that does an ordinary DAO update. The only requirement is that it's Public and lives on the object you passed to AddHostObjectToScript.

The JavaScript side: two ways to call it

WebView2 host objects can be called two ways, and both are valid — pick whichever fits the call.

Async (recommended for anything that returns a value or does real work):

HTML
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Order Entry</title>
</head>
<body>
  <h1>New Order</h1>
  <input type="hidden" id="orderId" value="4521">
  <input type="number" id="orderTotal" step="0.01" value="129.99">
  <button onclick="saveOrder()">Save Order</button>
  <p id="status-2"></p>

  <script>
    async function saveOrder() {
      const vba = chrome.webview.hostObjects.vba;
      const id = Number(document.getElementById('orderId').value);
      const total = Number(document.getElementById('orderTotal').value);
      try {
        const result = await vba.SaveOrder(id, total);
        document.getElementById('status').textContent = result;
      } catch (e) {
        document.getElementById('status').textContent = 'Save failed: ' + e.message;
      }
    }
  </script>
</body>
</html>

chrome.webview.hostObjects.vba gives you a reference to the object registered under the name "vba"; calling a method on it returns a JavaScript Promise, so you await it to get the return value (SaveOrder's confirmation string, in this case).

Sync (fire-and-forget, or when you don't want to deal with a Promise):

JavaScript
window.chrome.webview.hostObjects.sync.vba.OnReady();

The .sync accessor calls the VBA method and returns its result immediately instead of a Promise — useful for a quick notification like "the page finished loading" where you don't need async/await machinery around it. AddHostObjectToScript "vba", Me in the ready handler is what makes the form itself answer to sync.vba.OnReady(); the form would need a matching Public Sub OnReady().

What should happen

The user opens the order page, types or edits the total, and clicks Save Order. JavaScript reads the two field values, calls vba.SaveOrder(id, total), and waits. VBA's SaveOrder function runs the UPDATE, builds a confirmation string, and returns it. The await resolves, and the page's status paragraph shows Order 4521 saved: $129.99. If the DAO call throws (bad SQL, locked table, whatever), the catch block in the JavaScript shows Save failed: ... instead — the error crosses the bridge as a JavaScript exception.

Go deeper in Part II

Chapter 6: Sending Messages Between VBA and the Page

6.1 Two ways to talk to the page

So far you've called methods on m_lv directly and let JavaScript run inside the page. That covers the "VBA drives the page" direction. This chapter covers the other channel: web messaging, a loose, event-style pipe between VBA and JavaScript that either side can use to notify the other without a direct method call.

Web messaging is different from a host object (a VBA/COM object you expose into the page so JavaScript can call its methods directly, typed argument by typed argument). A host object is a phone call — JavaScript dials a specific method and gets a specific answer. Web messaging is more like a pager — one side posts a message, the other side is listening and reacts if it cares to. You'll use web messaging for things like "tell the page a new order arrived" or "tell VBA the user clicked Save on the page," where you don't need a return value and don't want the two sides tightly coupled.

Both directions share one JavaScript entry point on the page: chrome.webview.addEventListener('message', function(event) { ... }). Everything VBA posts to the page — JSON or plain string — arrives through that same listener, in event.data.

6.2 Sending data to the page: PostWebMessageAsJson and PostWebMessageAsString

Suppose frmDashboard hosts m_lv showing a live Orders dashboard page. When a new order is saved in Access, you want the page to update without VBA reaching into the DOM itself.

PostWebMessageAsJson

Use this when the page needs structured data.

VBA
' In frmDashboard, after saving a new order:
m_lv.PostWebMessageAsJson "{""type"":""orderCount"",""value"":42}"
JavaScript
// dashboard.html
chrome.webview.addEventListener('message', function(event) {
    var data = event.data;  // {type: "orderCount", value: 42}
    if (data.type === 'orderCount') {
        document.getElementById('divStatus').textContent = 'Orders today: ' + data.value;
    }
});

What should happen: the moment PostWebMessageAsJson runs, the listener fires and divStatus updates — no page reload, no re-navigation.

Reg-Free uses the pool equivalent: pool.PostWebMessageAsJson idx, "{""type"":""orderCount"",""value"":42}". Chapter 17 covers that deployment model.

PostWebMessageAsString

Use this when you just need to get a plain string across — a notice, a log line, a short instruction — without building JSON.

VBA
m_lv.PostWebMessageAsString "New order received!"
JavaScript
chrome.webview.addEventListener('message', function(event) {
    console.log(event.data);  // "New order received!"
});

The same listener receives both kinds of messages; check typeof event.data or the shape of the value if a page needs to tell JSON messages apart from plain strings.

Reg-Free uses the pool equivalent: pool.PostWebMessageAsString idx, "New order received!". Chapter 17 covers that deployment model.

See Part II -> Web Messaging for the full parameter reference.

6.3 Receiving messages from the page

The page can post back to VBA with chrome.webview.postMessage(...). How VBA picks that up depends on the mode.

Registered Mode: the WebMessageReceived event

Events fire in Registered Mode only. There is no equivalent event in Reg-Free mode — see the callback pattern below for that.

VBA
Private Sub LiteView2Ctrl1_WebMessageReceived(ByVal message As String, ByVal source As String)
    ' message is whatever the page passed to chrome.webview.postMessage(...)
    ' Raised after WebView2's callback has returned: JsonGetValue, ExecuteScript
    ' and the other synchronous calls work here (see 6.5).
End Sub

On the page:

JavaScript
// User clicks Save on the Orders form embedded in the page
chrome.webview.postMessage(JSON.stringify({ action: 'refreshOrders' }));

What should happen: saving on the page fires LiteView2Ctrl1_WebMessageReceived in VBA with that JSON string as message. Section 6.5 covers the one rule you need to follow before you act on it.

Reg-Free Mode: SetWebMessageCallback and ClearWebMessageCallback

Reg-Free has no events, so you register a Public Sub by name instead. Like SetReadyCallback (Chapter 17), SetWebMessageCallback only registers where a future message should be routed — it doesn't touch the page or wait for one — so it's safe alongside the rest of the pool/idx setup in Form_Load, before the browser is ready:

VBA
' In Form_Load, alongside CreateInControl / SetReadyCallback:
pool.SetWebMessageCallback idx, Application, "CB_frmDashboard"

' In modLV2Callbacks.bas:
Public Sub CB_frmDashboard(ByVal message As String, Optional ByVal source As String = "")
    If IsFormLoaded("frmDashboard") Then Forms("frmDashboard").HandleMessage message
End Sub

' In frmDashboard's module:
Public Sub HandleMessage(ByVal message As String)
    If InStr(message, """action"":""refreshOrders""") > 0 Then
        ' requery the Orders list, etc.
    End If
End Sub

Detach the callback when the form is done with it (Form_Unload is a typical place):

VBA
pool.ClearWebMessageCallback idx

The Registered-mode equivalent of clearing is m_lv.ClearWebMessageCallback, though there's rarely a reason to call it — you'd normally just stop reacting to the event instead of detaching it.

See Part II -> Web Messaging for the exact callback macro signature and dispatch rules.

6.4 Checking whether messaging is enabled: IsWebMessageEnabled

IsWebMessageEnabled is a read/write Boolean — messaging can be turned off entirely if a page shouldn't be allowed to talk back to VBA.

VBA
' Registered:
Debug.Print "Web messaging: " & m_lv.IsWebMessageEnabled   ' Get
m_lv.IsWebMessageEnabled = True                              ' Enable
VBA
' Reg-Free:
Debug.Print "Web messaging: " & pool.GetWebMessageEnabled(idx)
pool.SetWebMessageEnabled idx, True

Turn this off if a page shouldn't be allowed to exchange messages with VBA at all.

6.5 Where synchronous calls work, and where they don't

Note

WebMessageReceived is raised after WebView2's own callback has returned, so handle the message right there: JsonGetValue, ExecuteScript and PushRecordset all work inside it. Synchronous calls fail (error &H80040203) in two places only: inside inline events such as WebViewReady / NavigationStarting, and inside VBA methods the page is calling through a host object. Inside a host method, use only calls that do not wait (ExecuteScriptAsync, PostWebMessageAsJson, the JSON helpers, DAO). See Critical Safety Warnings #1.

VBA
' Fine: WebMessageReceived runs after WebView2's callback has returned.
Private Sub LiteView2Ctrl1_WebMessageReceived(ByVal message As String, ByVal source As String)
    Dim orderId As Variant
    orderId = m_lv.JsonGetValue(message, "orderId")
    ' ... act on orderId; ExecuteScript and the other synchronous calls work here too ...
End Sub

6.6 A note on the window.lv facade

LiteView2 also offers a window.lv JavaScript facade (lv.call/lv.on/lv.send/lv.bind, Registered Mode only) built on top of this same messaging model. It's introduced properly in Part II once you're comfortable with the underlying messaging model covered in this chapter.

6.7 See Part II for more

Chapter 7: Reading and Changing the Web Page From VBA

Once a page is loaded in LiteView2, you can read and change it from VBA the same way JavaScript running inside the page could: read what a user typed into a field, fill in a form before submitting it, swap a block of HTML, check whether an element exists yet, tick a checkbox, pick a dropdown option, move focus, scroll something into view, or pull the whole page's HTML or text back into VBA.

Every method in this chapter addresses an element one of three ways: by its id attribute, by its name attribute, or by a CSS selector. id-based methods are the ones you'll reach for first, because most forms you build already give their fields unique IDs and the calls read almost like plain English (GetElementValueById, SetElementValueById). CSS selectors come in when an element doesn't have a convenient ID of its own — a particular row in a table, or a button that only makes sense in the context of one specific form. name-based methods cover the older HTML convention of identifying form fields by name instead of id.

The examples below use m_lv (As LiteView2Lib.LiteView2Ctrl), the Registered-mode variable used throughout Part I. Registration-Free deployments call the same methods on the pool object instead — pool.SetElementValueById idx, "txtName", "Jane Smith" instead of m_lv.SetElementValueById "txtName", "Jane Smith" — the method name and arguments are identical, just prefixed with the browser index. Chapter 17 covers the Reg-Free pool model in full; nothing further in this chapter calls that difference out again.

All examples reference cookbook_test.html, the test page shipped with LiteView2. It's a small customer-contact page: a name/email form, a results panel, a data table, a checkbox pair, a country dropdown, and a plain contact form further down the page. The excerpt below shows the elements this chapter's recipes touch — the shipped page has more on it than this, but these are the pieces you'll see reused example to example.

HTML
<h2 id="pageTitle">Cookbook Test Page</h2>

<input type="text" id="txtName-3" data-role="primary" value="John Doe">
<input type="email" id="txtEmail-2" value="">
<button id="btnSubmit" class="primary">Submit</button>

<div id="divResults-4">Results will appear here</div>
<div id="divStatus">ready</div>
<div id="errorDiv" class="error" style="display:none">Please correct the errors below.</div>

<table id="tblData">
  <tr><th>Order</th><th>Total</th></tr>
  <tr><td>1001</td><td>42.00</td></tr>
  <tr><td>1002</td><td>17.50</td></tr>
</table>

<form id="frmContact">
  <input type="text" id="frmName">
  <textarea id="frmMsg"></textarea>
  <button type="submit">Send</button>
</form>

<input type="checkbox" id="chkAgree">
<input type="checkbox" id="chkNewsletter">

<select id="ddlCountry">
  <option value="US">United States</option>
  <option value="DE">Germany</option>
</select>

<div id="scrollTarget">You've reached the bottom section.</div>

<!-- a simpler form addressed by "name" instead of "id" -->
<form>
  <input type="text" name="userName" value="John Doe">
  <input type="email" name="userEmail" value="john@example.com">
  <input type="checkbox" name="agree">
</form>

7.1 Reading and writing an input's value by ID

Goal: read what a user (or the page itself) put into a text field, and fill fields in from VBA — the two operations you'll use constantly when a page's form doubles as your data-entry screen.

VBA
Dim custName As String
custName = m_lv.GetElementValueById("txtName")
Debug.Print "Name: " & custName          ' "Name: John Doe"

m_lv.SetElementValueById "txtName", "Jane Smith"
m_lv.SetElementValueById "txtEmail", "jane@example.com"

What happens: GetElementValueById returns the current value of an input, textarea, or select element as a string. SetElementValueById writes a new value into it, exactly as if the user had typed it (or, for a <select>, picked it) and left the field.

See Part II → DOM Manipulation Reference → Element Values for the full parameter and return-type details.

7.2 Clicking an element by ID

Goal: trigger a button the same way a user clicking it would, without re-implementing whatever the page's own JavaScript does when that button is clicked.

VBA
m_lv.SetElementValueById "txtName", "Jane Smith"
m_lv.SetElementValueById "txtEmail", "jane@example.com"
m_lv.ClickElementById "btnSubmit"

What happens: ClickElementById dispatches a click on the element with that ID. If the page has a click handler wired to that button — validation, an AJAX call, whatever the page author built — it runs exactly as it would for a real mouse click.

See Part II → DOM Manipulation Reference → Clicking Elements.

7.3 Reading and changing page content: HTML, text, and attributes

Goal: push a chunk of markup or plain text into a results panel, and read or change the attributes a page uses to tag its elements — the tools you reach for once a single field value isn't the whole story.

VBA
' HTML — parsed as markup; use when you're deliberately building HTML
Dim html As String
html = m_lv.GetInnerHtmlById("divResults")          ' "Results will appear here"
m_lv.SetInnerHtmlById "divResults", "<p>Found <b>42</b> items</p>"

' Plain text — never interpreted as markup; use for ordinary strings
Dim status As String
status = m_lv.GetElementTextById("divStatus")       ' "ready"
m_lv.SetElementTextById "divStatus", "Status: processing..."

' Attributes — data-* tags, placeholder, href, class, or any other HTML attribute
Dim role As String
role = m_lv.GetElementAttributeById("txtName", "data-role")   ' "primary"
m_lv.SetElementAttributeById "txtName", "data-role", "secondary"
m_lv.RemoveElementAttributeById "txtName", "data-role"

What happens: GetInnerHtmlById/SetInnerHtmlById read and replace everything inside an element as an HTML string — <b>42</b> becomes a real bold element on the page, not literal text. GetElementTextById/SetElementTextById do the same job for plain text: reading strips all tags out, and writing never interprets <, >, or & as markup. GetElementAttributeById/SetElementAttributeById/RemoveElementAttributeById read, write, and delete any HTML attribute on an element, not just value.

Caution

this is the distinction to keep straight between the HTML calls and the text call above. Use SetInnerHtmlById only when you're deliberately building markup. Use SetElementTextById for ordinary text — especially anything from user input or an external data source — so a value like O'Brien & Sons <VIP> can never be misinterpreted as HTML.

See Part II → DOM Manipulation Reference for GetOuterHtmlById/SetOuterHtmlById (the same idea as the HTML calls above, but including the element's own tag) and the full parameter/return details for every method above.

7.4 Working with form controls: existence checks, checkboxes, and dropdowns

Goal: guard code against an element that might not exist yet, and read or set the two other common form-control types besides plain text inputs.

VBA
' Guard before acting on an element that might not be there yet
If m_lv.ElementExistsById("errorDiv") Then
    Debug.Print "Error div found"
End If

' Checkboxes — a plain Boolean instead of an attribute or value string
m_lv.SetCheckboxById "chkAgree", True
If m_lv.GetCheckboxById("chkAgree") Then Debug.Print "User agreed"

' Dropdowns — matched by the option's underlying value, not its visible text
m_lv.SelectOptionById "ddlCountry", "DE"            ' selects "Germany"
Dim country As String
country = m_lv.GetSelectedOptionById("ddlCountry")  ' "DE"

What happens: ElementExistsById returns True/False without raising an error, so it's safe to call as a guard before any Get/Set-by-ID method. SetCheckboxById/GetCheckboxById check or uncheck a box and read its state as a Boolean. SelectOptionById matches against the <option> elements' value attribute, not their displayed text; GetSelectedOptionById returns that same value for whichever option is currently selected.

See Part II → DOM Manipulation Reference for the full parameter details.

7.5 Focus, scrolling, and submitting a form

Goal: move keyboard focus to a field after a validation failure, scroll a section into view, and submit a form once its fields are filled in from VBA.

VBA
m_lv.FocusElementById "txtEmail"
m_lv.ScrollToElementById "scrollTarget"

m_lv.SetElementValueById "frmName", "John Doe"
m_lv.SetElementValueById "frmMsg", "Hello"
m_lv.SubmitFormById "frmContact"

What happens: FocusElementById sets keyboard focus the same as a click or Tab would. ScrollToElementById scrolls the element into view without changing focus. SubmitFormById submits the form the same way clicking its Submit button would — any client-side validation or onsubmit handling the page defines still runs; this triggers the page's own logic rather than bypassing it.

See Part II → DOM Manipulation Reference for the full parameter details.

7.6 Reading the whole page

Goal: capture the entire page for logging, diagnostics, or exporting a rendered report, rather than one element at a time.

VBA
Dim fullHtml As String, plainText As String
fullHtml = m_lv.GetPageHtml
plainText = m_lv.GetPageText

What happens: GetPageHtml returns the complete HTML of the loaded page as one string. GetPageText returns the same page's visible text with markup stripped — the same HTML-vs-text distinction as section 7.3, applied to the whole document.

7.7 Targeting elements a CSS selector can reach that an ID can't

Every recipe so far has assumed the element you want already has a convenient id. Real pages don't always cooperate — a table row usually doesn't have its own ID, and a button inside one form might share a class with buttons in three other forms. A CSS selector lets you describe where an element sits in the page instead of relying on it having a unique name.

A selector is the same kind of pattern used in a stylesheet: #id matches an ID, .class matches a class, tag matches an element type, and selectors can be chained to narrow down to one specific spot — table#tblData tr:nth-child(2) means "the second row inside the table whose ID is tblData"; form#frmContact button[type='submit'] means "the submit button inside the form whose ID is frmContact," even if other submit buttons exist elsewhere on the page.

VBA
m_lv.ClickElementBySelector "#btnSubmit"
m_lv.ClickElementBySelector "button.primary"
m_lv.ClickElementBySelector "form#frmContact button[type='submit']"
VBA
If m_lv.ElementExistsBySelector("table#tblData tr:nth-child(2)") Then
    Debug.Print "Table has at least 2 rows"
End If

What happens: ClickElementBySelector clicks the first element matching the given CSS selector; ElementExistsBySelector checks whether any element matches, returning a Boolean the same way ElementExistsById does. Both take any valid CSS selector, so they cover cases plain ID-based methods can't reach.

See Part II → DOM Manipulation Reference → CSS Selectors.

7.8 Addressing by name, and other variants — pointer to Part II

Two smaller families of DOM methods round out the catalog. You won't reach for these as often as the ID-based recipes above, so this section just shows the shape of them; Part II documents every one in full.

By name attribute, for pages built around HTML's older name-based form fields instead of id:

VBA
Dim email As String
email = m_lv.GetElementValueByName("userEmail")
Debug.Print "Email: " & email            ' "john@example.com"

m_lv.SetElementValueByName "userEmail", "new@example.com"
m_lv.ClickElementByName "agree"

These work exactly like their ...ById counterparts (section 7.1), just matching on the element's name attribute instead of its id.

OuterHTML, which replaces an element including its own tag — not just its contents:

VBA
m_lv.SetOuterHtmlById "divResults", "<div id=""divResults""><b>Replaced!</b></div>"

GetOuterHtmlById / SetOuterHtmlById and their ...ByName counterparts follow the same Get/Set pattern as GetInnerHtmlById / SetInnerHtmlById from section 7.3, except the tag itself is included in what's read or replaced.

See Part II → DOM Manipulation Reference → Name-Based Addressing and → Outer HTML for the complete parameter lists, including GetOuterHtmlByName / SetOuterHtmlByName.

Chapter 8: Moving Business Data Between VBA and JavaScript

The previous chapters got a page loaded into the control and let VBA call into it. This chapter is about the part most Access and Excel developers actually came for: getting real business data — recordsets, totals, lookups — out of VBA and onto the page, in a shape JavaScript can use directly.

The running example is a sales dashboard: an Access form (frmDashboard) hosts the LiteView2Ctrl (m_lv), and its page shows a monthly sales summary pulled from tblSales. We assume the page has already finished loading, as covered in earlier chapters — every call below runs from code that fires after that point (a button click, a form event, and so on).

Three members do the work in this chapter:

8.1 Pushing a Recordset to JavaScript with PushRecordset

What we're trying to accomplish

The dashboard page needs a table of monthly sales totals. Rather than building that table row-by-row from VBA (string-concatenating HTML, or making dozens of small BuildJson calls), we run one aggregate query in Access and hand the whole recordset to PushRecordset. It serializes the recordset to JSON and calls a JavaScript function of our choosing with the result.

Code

VBA
Dim rs As DAO.Recordset
Set rs = CurrentDb.OpenRecordset( _
    "SELECT Year(SaleDate) AS Yr, Month(SaleDate) AS Mo, " & _
    "       Sum(Quantity * UnitPrice) AS Total " & _
    "FROM tblSales " & _
    "GROUP BY Year(SaleDate), Month(SaleDate)", dbOpenSnapshot)
rs.MoveLast
rs.MoveFirst
m_lv.PushRecordset rs, "onSalesData"
rs.Close

JavaScript side

JavaScript
function onSalesData(rows) {
    // rows = [{Yr: 2024, Mo: 1, Total: 15234.50}, ...]
    rows.forEach(r => console.log(r.Yr + "-" + r.Mo + ": $" + r.Total));
}

onSalesData must already be defined in the page (a <script> block loaded with the page, same as the JS functions VBA calls in earlier chapters) — PushRecordset calls it by name, it does not define it for you.

What should happen

The page's onSalesData function runs once, with rows as a plain JavaScript array of objects — one object per recordset row, keyed by the query's column aliases (Yr, Mo, Total). From there it's ordinary JavaScript: render a table, feed a chart library, filter in memory, whatever the dashboard needs.

Cautions

Registration-Free mode uses the pool equivalent — pool.PushRecordset idx, rs, "onSalesData" — with the same dbOpenSnapshot / MoveLast+MoveFirst / 100,000-row rules. Chapter 17 covers the pool/idx deployment model in full.

See Part II → Data Bridge & JSON for the complete member reference.

8.2 Converting a Single Value to JSON with BuildJson

What we're trying to accomplish

Not everything is a full recordset. Sometimes you just need one VBA value — a string, a number, an array of names — turned into a JSON string: to log it, to build a payload for FireJsEvent (next section), or to hand-assemble a small piece of a larger script call. BuildJson does that conversion without touching the page at all.

Code

VBA
Dim json As String
json = m_lv.BuildJson("Hello World")   ' Returns: "Hello World"
json = m_lv.BuildJson(42)              ' Returns: 42
json = m_lv.BuildJson(Array(1, 2, 3))  ' Returns: [1,2,3]
Debug.Print json

What should happen

Each call returns a JSON-formatted string for the value passed in — a quoted string, a bare number, or a bracketed array, matching the VBA type given. No page navigation or JavaScript call happens; the conversion is pure VBA-side work.

That last point is worth pausing on: BuildJson works even without a WebView2 browser present. The control is doing JSON conversion as a service, independent of anything on screen. Chapter 9 goes into this in full — BuildJson is one entry point into a standalone JSON toolkit (JsonToArray, JsonToRowArray, and friends) that doesn't require a live browser to use.

Registration-Free mode calls the same operation through the pool, with the browser index as the first argument: pool.BuildJson(idx, Array("a", "b", "c")). Chapter 17 covers the pool/idx deployment model in full.

See Part II → Data Bridge & JSON for the complete member reference.

8.3 Notifying the Page with FireJsEvent

What we're trying to accomplish

PushRecordset is for handing over data. FireJsEvent is for handing over a signal — "something happened, here's a small detail payload" — that the page can listen for the standard browser way, with document.addEventListener, rather than exposing a specific callback function name for VBA to call. This suits things like "the dashboard just refreshed" or "a new order was saved," where several independent pieces of page script might all want to react.

Code

VBA
Dim detail As String
detail = m_lv.BuildJson("dataReady")   ' or build a richer object by hand, see below

m_lv.FireJsEvent "dataReady", "{""count"":42,""source"":""VBA""}"

The event detail is a JSON string you supply — here it's written out by hand (note the doubled quotes to embed " inside a VBA string literal); for anything more than a couple of fields, building it with BuildJson from an array or a dictionary-like structure is less error-prone than hand-quoting JSON in VBA.

JavaScript side

JavaScript
document.addEventListener('dataReady', function(e) {
    console.log(e.detail);  // {count: 42, source: "VBA"}
});

What should happen

Any listener already registered on the page fires with e.detail set to the parsed object from the JSON string VBA supplied. Unlike PushRecordset's named-function call, any number of listeners can react to the same event, and the page doesn't need to expose a function VBA knows about in advance.

Caution — no Reg-Free equivalent

Registration-Free mode has no direct FireJsEvent call. It falls back to ExecuteScriptAsync, dispatching the event manually with a hand-built JavaScript string:

VBA
' Use ExecuteScriptAsync to dispatch event manually
pool.ExecuteScriptAsync idx, _
    "document.dispatchEvent(new CustomEvent('dataReady'," & _
    "{detail:{count:42,source:'VBA'}}));"

This is more than the usual Reg-Free variable-naming difference, so it's called out here rather than folded into a one-line aside: in Registered mode you get a dedicated method; in Reg-Free mode you construct the equivalent JavaScript yourself. Chapter 17 covers the pool/idx deployment model, and ExecuteScriptAsync itself, in full.

See Part II → Data Bridge & JSON for the complete member reference.

Where to Go Next

Chapter 9: JSON Without Hand-Written VBA Parsing

If your project pulls data from a REST API, reads a config blob, or exchanges structured data with a page loaded in your browser control, you eventually need to pick fields out of a JSON string and, just as often, build one. VBA has no native JSON support, so most projects either write a hand-rolled parser or import a third-party module like JsonConverter.bas.

LiteView2 ships its own JSON engine — pure native C++, not a JavaScript library running in the browser — and exposes it as plain VBA function calls. You pass in a JSON string, you get a value, an array, or a modified JSON string back. No browser navigation is required for any of it, and as you'll see at the end of this chapter, you don't even need a browser control on the form to use it.

This chapter uses a recurring example: your VBA code has just received a JSON response describing a customer record and a small sales report, and you need to read fields out of it, build/modify JSON of your own, and turn a JSON array into something you can loop over or drop into an Excel range.

9.1 Reading values out of JSON

JsonGetValue

JsonGetValue pulls a single value out of a JSON string using a path expression. Use a dot to walk into nested objects.

VBA
Dim json As String
json = "{""name"":""John"",""age"":30,""address"":{""city"":""NYC""}}"

Debug.Print m_lv.JsonGetValue(json, "name")          ' "John"
Debug.Print m_lv.JsonGetValue(json, "age")            ' 30
Debug.Print m_lv.JsonGetValue(json, "address.city")   ' "NYC"

Registration-Free uses the pool equivalent — same method name, with the browser index (idx) as an extra leading argument; Chapter 17 covers that deployment model in full.

Note

WebMessageReceived is raised after WebView2's own callback has returned, so handle the message right there: JsonGetValue, ExecuteScript and PushRecordset all work inside it. Synchronous calls fail (error &H80040203) in two places only: inside inline events such as WebViewReady / NavigationStarting, and inside VBA methods the page is calling through a host object. Inside a host method, use only calls that do not wait (ExecuteScriptAsync, PostWebMessageAsJson, the JSON helpers, DAO). See Critical Safety Warnings #1.

JsonGetArrayLength and JsonGetArrayItem

VBA
Dim json As String
json = "{""items"":[10,20,30,40]}"

Dim count As Long
count = m_lv.JsonGetArrayLength(json, "items")
Debug.Print "Array has " & count & " items"   ' 4

JsonGetArrayItem fetches one element by index. Pass an empty path when the array is the JSON value itself, not a key inside an object:

VBA
Dim json As String
json = "[{""name"":""Alpha""},{""name"":""Beta""}]"

Dim item As String
item = m_lv.JsonGetArrayItem(json, "", 0)
Debug.Print item   ' {"name":"Alpha"}

JsonGetKeys

Returns the keys of an object at a path, as a JSON array string. An empty path means the root object.

VBA
Dim json As String
json = "{""name"":""John"",""age"":30,""city"":""NYC""}"

Dim keys As String
keys = m_lv.JsonGetKeys(json, "")
Debug.Print keys   ' ["name","age","city"]

JsonIsValid

Checks whether a string parses as JSON at all — useful before you trust an API response or a value a user typed into a text box.

VBA
Debug.Print m_lv.JsonIsValid("{""valid"":true}")   ' True
Debug.Print m_lv.JsonIsValid("{bad json}")          ' False

See Part II → JSON Helper for the complete signature list, including every Reg-Free form.

9.2 Building and modifying JSON

The mutation methods below are pure native C++ — they don't touch the WebView2 browser at all, so they work even before a page has finished loading. Each one accepts a JSON string and returns the modified JSON string; on failure the original JSON comes back unchanged, so always assign the return value back.

Starting points: JsonCreateObject and JsonCreateArray

VBA
Dim json As String
json = m_lv.JsonCreateObject()    ' {}
VBA
Dim json As String
json = m_lv.JsonCreateArray()     ' []

JsonSetValue

Sets a value at a path, creating any intermediate objects or arrays that don't exist yet. Array elements use name[index] syntax; gaps are padded with null.

VBA
Dim json As String
json = m_lv.JsonCreateObject()

' Simple values
json = m_lv.JsonSetValue(json, "name", "Imran")
json = m_lv.JsonSetValue(json, "age", 30)
json = m_lv.JsonSetValue(json, "active", True)

' Auto-creates the nested "address" object
json = m_lv.JsonSetValue(json, "address.city", "London")
json = m_lv.JsonSetValue(json, "address.country", "UK")

' Overwrite an existing value
json = m_lv.JsonSetValue(json, "name", "Ali")

' Array elements — auto-creates "scores" as an array
json = m_lv.JsonSetValue(json, "scores[0]", 95)
json = m_lv.JsonSetValue(json, "scores[1]", 88)

Debug.Print m_lv.JsonPrettyPrint(json)

JsonExists

Checks whether a path is present before you read or overwrite it.

VBA
Dim json As String
json = "{""user"":{""name"":""Imran""}}"

If m_lv.JsonExists(json, "user.name") Then Debug.Print "Found"

If Not m_lv.JsonExists(json, "user.email") Then
    json = m_lv.JsonSetValue(json, "user.email", "imran@example.com")
End If

JsonAppend

Appends a value to the end of an array at a path, creating the array if it isn't there yet.

VBA
Dim json As String
json = m_lv.JsonCreateObject()

json = m_lv.JsonAppend(json, "tags", "vba")
json = m_lv.JsonAppend(json, "tags", "com")
json = m_lv.JsonAppend(json, "tags", "webview2")
Debug.Print json   ' {"tags":["vba","com","webview2"]}

JsonMerge

Combines two JSON objects. The third argument controls shallow vs. deep merge, and the difference only shows up when a key on both sides is itself an object:

VBA
Dim base As String, overlay As String, json As String
base = "{""name"":""Imran"",""address"":{""city"":""London"",""zip"":""SW1""}}"
overlay = "{""age"":30,""address"":{""city"":""Manchester""}}"

' Shallow merge (False) — overlay's "address" REPLACES base's "address" entirely
json = m_lv.JsonMerge(base, overlay, False)
' {"name":"Imran","address":{"city":"Manchester"},"age":30}   <- zip is GONE

' Deep merge (True) — overlay's "address" is merged key-by-key into base's
json = m_lv.JsonMerge(base, overlay, True)
' {"name":"Imran","address":{"city":"Manchester","zip":"SW1"},"age":30}  <- zip survives

If you're merging a partial update (like a form that only edits address.city) into a full record and want to keep the fields the update didn't touch, use deep merge. Shallow merge is closer to a plain key-for-key overwrite.

More mutation methods (Part II)

JsonRemoveKey, JsonInsert, JsonCount, JsonClear, JsonPrettyPrint, JsonFlatten, and JsonUnflatten round out the mutation API — removing a key or array element, inserting into the middle of an array, counting keys/elements, emptying a container, pretty-printing for debugging, and flattening/unflattening nested JSON to and from dot-notation keys. They follow the same "pass JSON string in, get JSON string back" shape as the methods above. Part II → JSON Helper documents each one in full, along with a complete worked example that builds a report document from JsonCreateObject() through JsonSetValue, JsonAppend, JsonExists, JsonCount, and JsonPrettyPrint in one pass.

Caution

On the Reg-Free pool, JsonSetValue, JsonRemoveKey, and JsonToRowArray are exposed as JsonSetValue2, JsonRemoveKey2, and JsonToRowArray2 — the 2 suffix just avoids a COM name collision on those three methods. Everything else keeps its Registered-mode name.

9.3 Turning JSON into VBA arrays

Reading values one path at a time is fine for a handful of fields. When you have an array of records — a customer list, an order history, a report's line items — and you want to loop over it or dump it into an Excel range, converting the whole array to a VBA array in one call is faster and far less code.

JsonToArray

Converts a JSON array to a plain 2D VBA array. Suppose an API call handed you a small table of daily figures:

VBA
Dim json As String
json = "[{""Date"":""2024-01-01"",""Open"":100,""Close"":105}," & _
       "{""Date"":""2024-01-02"",""Open"":105,""Close"":110}]"

Dim arr As Variant
arr = m_lv.JsonToArray(json)
' arr is a 2D array: arr(1,1)="2024-01-01", arr(1,2)=100, arr(1,3)=105, ...

JsonToArray gives you raw values, indexed from arr(1,1), with no header row.

JsonToRowArray

JsonToRowArray does the same job but adds a header row, and it types each cell in VBA terms rather than leaving everything as Variant/string — which matters when you're writing straight into an Excel range or comparing values later in code. Row 1 holds the column headers (taken from the JSON keys); rows 2+ hold the data.

VBA
Dim json As String
json = "[{""Name"":""Imran"",""Age"":30,""Active"":true}," & _
       "{""Name"":""Ali"",""Age"":25,""Active"":false}]"

Dim arr As Variant
arr = m_lv.JsonToRowArray(json)
' arr(1,1)="Name"  arr(1,2)="Age"  arr(1,3)="Active"   <- headers
' arr(2,1)="Imran" arr(2,2)=30     arr(2,3)=True         <- data
' arr(3,1)="Ali"   arr(3,2)=25     arr(3,3)=False

Dim r As Long, c As Long
For r = 2 To UBound(arr, 1)
    For c = 1 To UBound(arr, 2)
        Debug.Print arr(r, c);
    Next c
    Debug.Print
Next r

That array is also exactly the shape Range.Value = arr expects in Excel — headers in row 1, data below — so writing a JSON array straight into a worksheet is usually a one-line assignment once you have arr.

Type mapping (JSON type → VBA type in the returned array):

JSON TypeVBA Type
stringvbString
number (integer)vbLong
number (decimal)vbDouble
booleanvbBoolean
nullvbEmpty
object / arrayvbString (serialized JSON)

A nested object or array inside a row comes back as a JSON string in that cell, not expanded into more columns — feed it back through JsonGetValue or JsonToRowArray if you need to drill into it.

Reg-Free note: use JsonToRowArray2 here (see the caution at the end of the previous section).

JsonToArrayMaxSize (Property)

JsonToArrayMaxSize is a Registered-control property (Long, read/write) that caps how large a JSON string JsonToArray and JsonToRowArray will accept, in bytes. Default is 52428800 (50MB).

VBA
Debug.Print m_lv.JsonToArrayMaxSize    ' 52428800
m_lv.JsonToArrayMaxSize = 104857600    ' raise the cap to 100MB

The Reg-Free pool doesn't expose this as a settable property — it always applies the built-in default.

9.4 Using the JSON engine with no browser control at all

Everything above assumed you had a m_lv control (or a pool/idx pair) already on a form. The JSON engine is also reachable as a fully standalone COM object that has nothing to do with WebView2 or a browser control:

VBA
Dim json As Object
Set json = CreateObject("LiteView2.Json")

Dim result As String
result = json.Append(json, path, value)
VBA
Dim json As Object
Set json = CreateObject("LiteView2.Json")

Dim result As String
result = json.Clear(json, path)

This matters for a project that has no on-screen use for a browser at all — an Access module that calls a REST API and needs to pick apart the response, a scheduled Excel macro that reshapes a JSON export, a class module in a service-style VB6 app. You get the same JSON engine, same method names, without adding a LiteView2Ctrl to any form and without a pool or browser index anywhere in the code.

MaxSize (Property)

The standalone JSON object also documents a MaxSize property — the byte cap applied to Parse/ToArray/ToRowArray calls. Default is 50MB; documented range is 1KB–500MB.

VBA
Dim value As Long
pool.GetMaxSize idx, value
VBA
pool.SetMaxSize idx, newValue   ' newValue As Long

Note the calling shape here is different from the read methods earlier in this chapter: GetMaxSize/SetMaxSize are Sub calls that take the value as a ByRef output/input parameter (GetMaxSize idx, value), not functions that return the value directly.

Note

The reference entry this is drawn from tags MaxSize as Mode: ILV2Json (standalone object), but the Get/Set code it documents is the Reg-Free pool form — pool.GetMaxSize idx, value / pool.SetMaxSize idx, newValue — not a call through the standalone json object shown above for Append/Clear. The documentation doesn't show a json.MaxSize form. Treat the pool form above as what's actually documented for this property, and see Part II → JSON Helper for the complete, unresolved picture of how MaxSize is meant to be reached from each mode.

Chapter 10: The Higher-Level Two-Way Script Bridge

By now you've navigated a page, called ExecuteScript to run a line of JavaScript, exposed a host object so the page can call back into VBA, and passed a web message across the boundary. All of that still works, and none of it goes away. This chapter is not a repeat of Chapter 4 — it introduces a different tool that sits on top of what you already know: the Two-Way Script Bridge.

10.1 Why bind an alias instead of building more strings

Once a page has grown past a handful of ExecuteScript calls, you start feeling two problems:

The bridge fixes both. You bind an alias once to a JavaScript object on the page, and from then on you read and write its properties or call its methods almost like it was a native form control:

VBA
m_lv.SetScriptProperty "page", "Title", "Customers"
total = m_lv.CallScriptSync("page", "computeTotal", 2, 3)

No string concatenation, and total comes back as a real typed Variant — a number, in this case — not text you have to CLng() yourself.

The examples in this chapter assume the page exposes a JavaScript object named window.PageController. Here is a self-contained page you can paste into any of the navigation techniques from earlier chapters:

HTML
<script>
  window.PageController = {
    Title: "Untitled",
    computeTotal: function (a, b) { return (a || 0) + (b || 0); },
    showToast:    function (msg)  { document.title = msg; }
  };
</script>

Bind once, after the page that defines the object has loaded: in NavigationCompleted (Registered), or later from ordinary code. A bind without LV2_BIND_VALIDATE also works in WebViewReady / OnBrowserReady and is resolved lazily. Inside WebViewReady, other inline events and host-object methods, a validating bind fails at once with &H80040203 and changes no binding. Every method below refers back to that binding by its alias.

Registration-Free code follows the pool equivalent (pool/idx instead of m_lv); Chapter 17 covers that deployment model in full. It is shown once per method here for completeness, but the rest of the chapter's prose sticks to Registered mode.

10.2 BindScriptObject

BindScriptObject binds a short alias to a JavaScript object expression. Every other bridge call — CallScript, CallScriptSync, GetScriptProperty, SetScriptProperty — refers to the object by that alias instead of re-stating the JavaScript path each time.

VBA
m_lv.BindScriptObject "page", "window.PageController"

Reg-Free: pool.BindScriptObject idx, "page", "window.PageController".

By default (flag 0), the object is resolved lazily — the bind call itself always succeeds, and the first bridge call that actually touches the object is where a "not found" error would surface. Pass a flag as the optional third argument to change that:

VBA
' Fail immediately if window.PageController doesn't exist yet:
m_lv.BindScriptObject "page", "window.PageController", 1   ' Validate

Bind flags (LV2_BIND_FLAGS)

Flags are combined with +.

FlagValueMeaning
(none)0Default — resolve lazily; the first call surfaces any resolution error.
Validate1Resolve the object at bind time; return an error immediately if it's missing.
Transient2Drop the binding on the next navigation instead of re-resolving it.
RawExpression4Accept an arbitrary JavaScript expression instead of a simple object path.
Async8Reserved — accepted but has no effect in this release.
FailIfBound16Return an error instead of silently replacing an existing binding.
FollowResolution32Re-evaluate the expression on every call (tracks reassignment) instead of capturing the object once at bind time.

Caution

RawExpression accepts an arbitrary JavaScript expression as the bind target instead of a restricted object-path form. By passing it, you accept the injection risk yourself — only combine it with strings you built, not with anything that came from a user, a grid cell, or an external file.

To combine flags, add the values — e.g. 1 + 16 validates immediately and refuses to silently replace an existing binding.

10.3 UnbindScriptObject

Releases a binding. Idempotent — unbinding an alias that was never bound, or was already unbound, simply returns success.

VBA
m_lv.UnbindScriptObject "page"

Reg-Free: pool.UnbindScriptObject idx, "page".

10.4 CallScript — fire-and-forget

Calls a method on the bound object without waiting for a result.

VBA
m_lv.CallScript "page", "showToast", "Saved!"

Reg-Free: pool.CallScript idx, "page", "showToast", "Saved!".

Up to 8 arguments are supported; trailing omitted arguments are ignored.

Caution

a JavaScript exception thrown during a fire-and-forget CallScript is not reported back to VBA — the call still returns as if it succeeded. If you need to know whether the call actually worked, use CallScriptSync instead.

10.5 CallScriptSync — blocking, typed result

Calls a method and blocks until it returns, delivering the result as a typed Variant.

VBA
Dim total As Variant
total = m_lv.CallScriptSync("page", "computeTotal", 2, 3)
Debug.Print total          ' 5  (a real number, not a string)

Reg-Free: total = pool.CallScriptSync(idx, "page", "computeTotal", 2, 3).

Caution

if the JavaScript method returns a Promise, CallScriptSync does not wait for it — it fails with LV2_BRIDGE_PROMISE_RETURNED. CallScriptSync is for synchronous JavaScript functions only; a method that returns a Promise needs a different approach (see Part II under the bridge reference for the full picture).

10.6 GetScriptProperty / SetScriptProperty

Read or write a property of the bound object as a typed Variant.

VBA
Dim caption As Variant
caption = m_lv.GetScriptProperty("page", "Title")

m_lv.SetScriptProperty "page", "Title", "Customers"

Reg-Free: pool.GetScriptProperty(idx, "page", "Title") and pool.SetScriptProperty idx, "page", "Title", "Customers".

Reading a property whose value is a function returns the error LV2_BRIDGE_PROPERTY_IS_FUNCTION — you can use that deliberately as a "does this method exist on the page?" probe before calling it.

Caution

a successful SetScriptProperty call does not guarantee the value stuck. Assigning to a read-only JavaScript property is silently ignored by the page — no error, no exception, the call just returns success. If the write matters (a title the user needs to see change, a setting a chart reads before redrawing), read the property back with GetScriptProperty afterward to confirm it actually took.

10.7 GetLastBridgeError

Retrieves the last bridge error for this browser as a numeric code (an HRESULT) plus a message. The slot is overwritten on every error and is never auto-cleared, so check it right after the call that might have failed.

VBA
On Error Resume Next
Dim v As Variant
v = m_lv.CallScriptSync("page", "noSuchMethod")
If Err.Number <> 0 Then
    Dim code As Long, msg As String
    m_lv.GetLastBridgeError code, msg
    Debug.Print Hex(code) & " - " & msg     ' 80040503 - ...
End If
On Error GoTo 0

Reg-Free: pool.GetLastBridgeError idx, code, msg.

Bridge error codes (LV2_BRIDGE_ERR)

These surface as Err.Number and are also returned by GetLastBridgeError.

ConstantHexWhen
LV2_BRIDGE_ALIAS_NOT_FOUND&H80040501Call on an alias that was never bound.
LV2_BRIDGE_OBJECT_NOT_RESOLVED&H80040502The bound expression evaluates to nothing on the page.
LV2_BRIDGE_METHOD_NOT_FOUND&H80040503No method of that name on the object.
LV2_BRIDGE_PROPERTY_NOT_FOUND&H80040504No property of that name on the object.
LV2_BRIDGE_JS_EXCEPTION&H80040505The JavaScript threw — see the message.
LV2_BRIDGE_PROMISE_RETURNED&H80040506A sync call received a Promise; use a synchronous method.
LV2_BRIDGE_TIMEOUT&H80040507The call did not complete within 30 seconds.
LV2_BRIDGE_NOT_READY&H80040508The browser isn't ready yet.
LV2_BRIDGE_INVALID_ARG&H80040509Bad alias/member name, or a value that can't be passed.
LV2_BRIDGE_INVALID_EXPRESSION&H8004050AThe bind expression isn't a safe object path (use RawExpression to override).
LV2_BRIDGE_REENTRY_BLOCKED&H8004050BToo many nested synchronous calls.
LV2_BRIDGE_ALIAS_ALREADY_BOUND&H8004050CRebind blocked because FailIfBound was set.
LV2_BRIDGE_PROPERTY_IS_FUNCTION&H8004050DGetScriptProperty target is a function.
(no constant) E_LV2_SYNC_REENTRANT&H80040203A synchronous bridge call (CallScriptSync, GetScriptProperty, SetScriptProperty, BindScriptObject with LV2_BIND_VALIDATE) was made inside an inline event or a host-object call. Nothing was sent. Use CallScript / ExecuteScriptAsync there, or call after the handler returns.

See Part II → Two-Way Script Bridge Reference for the complete member list and every argument variant.

10.8 Real-world: a live chart driven from a query

This is the pattern that makes the bridge worth the extra setup step: bind once, then push new data and pull the user's selection back, all with typed values instead of ad-hoc strings.

VBA
' 1. load a page that defines window.Dashboard, then bind it
m_lv.NavigateToStringSync DashboardHtml()      ' your page (defines window.Dashboard)
m_lv.BindScriptObject "chart", "window.Dashboard"

' 2. drive the chart from VBA
m_lv.SetScriptProperty "chart", "Title", "Sales by Category"
m_lv.CallScript "chart", "setData", Array(120, 340, 80)   ' array arrives in JS as [120,340,80]

' 3. read the user's selection back as a typed value
Dim picked As Variant
picked = m_lv.CallScriptSync("chart", "getSelectedCategory")
If Len(CStr(picked)) > 0 Then
    Me.Filter = "Category='" & picked & "'"
    Me.FilterOn = True
End If

The Access form here re-filters itself the moment the user clicks a slice of a chart living inside the WebView2 page — the same round trip you'd use to refresh an Orders or Inventory dashboard from a live query.

10.9 Choosing the right tool

By this chapter you have four ways to move data or trigger behavior across the VBA ↔ JavaScript boundary. They are not competitors — most real screens use two or three of them together.

MechanismDirectionWhat you get backBest for
ExecuteScriptVBA → JS, one-shotA string result you parse yourself (if you need one at all)Running a single line of script once — no repeated access to the same object needed
Host objectJS → VBAThe page calls a VBA method directlyLetting the page-side code trigger VBA logic on its own initiative (a button click inside the page, a JS-side validation failure)
Web messageVBA ↔ JS, message-basedA message your handler parsesLoosely-coupled, event-style notifications where you don't need a typed round trip
Two-Way Script Bridge (this chapter)VBA ↔ JS, bound aliasA typed Variant from every call/readRepeated, ongoing access to one known JavaScript object — reading and writing its properties and calling its methods as if it were a native control

Reach for the bridge when you find yourself binding to the same JavaScript object over and over — a chart, a form controller, a report viewer — rather than firing one-off ExecuteScript strings at it. Reach for ExecuteScript, a host object, or a web message when the interaction really is a one-shot script, a page-initiated callback, or a loose notification, respectively — Chapter 4 covers those in depth.

See Part II → Two-Way Script Bridge Reference for the exhaustive member list, and Chapter 17 for the Reg-Free (pool/idx) deployment model referenced throughout this chapter.

Chapter 11: Navigation, Browser UI and User Experience

WebView2 is a full browser engine, and by default it behaves like one: right-click brings up a context menu with "Inspect", Ctrl+scroll changes the zoom level, and a new window from a link opens as a real popup window. For a public-facing consumer app that's usually fine. For an internal line-of-business screen — an Orders dashboard embedded in an Access form, a Customer report opened from Excel — it's usually not what you want, and it's not always obvious how to turn it off.

This chapter walks through the browser-chrome and UX settings you're most likely to touch on a real internal application: context menus, DevTools, the status bar, zoom, popup handling, and find-in-page. All of these are simple Boolean, numeric, or string properties (plus a handful of find-in-page methods) — there's no async callback or DOM work involved, so this is a good chapter to work through even if you're still getting comfortable with the rest of the control.

Every example below uses the Registered ActiveX control, m_lv As LiteView2Lib.LiteView2Ctrl, which is the default for the rest of Part I. Registration-Free deployments expose the same behavior through pool-style calls (for example pool.SetZoom idx, 1.5 instead of m_lv.ZoomFactor = 1.5) — Chapter 17 covers that deployment model and its calling convention in full. As with any property on the control, set these after the browser has finished initializing, not immediately after Set m_lv = ... — the ready-state events were covered earlier in Part I.

The scenario used throughout: frmDashboard, an Access form that hosts m_lv and shows an internal Orders/Customers report page.

11.1 Context Menus and DevTools

The two most common lockdown settings for an internal app: should right-click show the browser's context menu, and should end users be able to open DevTools (F12) and start poking at your page's HTML, JavaScript, and network traffic?

AreDefaultContextMenusEnabled

Boolean, read/write. Turns the browser's built-in right-click context menu on or off.

VBA
Debug.Print m_lv.AreDefaultContextMenusEnabled

m_lv.AreDefaultContextMenusEnabled = False       ' Disable right-click menu

AreDevToolsEnabled

Boolean, read/write. Turns F12 DevTools on or off.

VBA
m_lv.AreDevToolsEnabled = False   ' Disable F12

For a shipped internal tool, a common pattern is to disable both in the production build and leave them enabled in a debug build, so you (and your support desk) can still inspect the page when something goes wrong:

VBA
m_lv.AreDefaultContextMenusEnabled = Not gblnProductionBuild
m_lv.AreDevToolsEnabled = Not gblnProductionBuild

See Part II -> Settings and Browser Behavior for the complete property reference, including the Reg-Free equivalents.

11.2 Status Bar

IsStatusBarEnabled and StatusBarText

IsStatusBarEnabled turns the browser's status bar overlay on or off. StatusBarText is the read-only string currently shown in it — in a normal browser, this is typically the target URL when the mouse is hovering over a hyperlink.

VBA
m_lv.IsStatusBarEnabled = True

' Elsewhere, e.g. on a timer or a mouse-move handler:
Debug.Print m_lv.StatusBarText

StatusBarText is read-only — you read what the browser is currently showing, you don't set it. If you want your own custom status display in an Access form (a label showing the hovered link, for example), read StatusBarText and write it into your own control rather than relying on the browser's built-in overlay.

See Part II -> Settings and Browser Behavior for the complete property reference.

11.3 Zoom

ZoomFactor and IsZoomControlEnabled

ZoomFactor (Double, read/write) is the current zoom level, where 1.0 is 100%. IsZoomControlEnabled (Boolean, read/write) turns end-user Ctrl+scroll zooming on or off.

VBA
Debug.Print "Zoom: " & m_lv.ZoomFactor * 100 & "%"

m_lv.ZoomFactor = 1.5              ' 150%, e.g. for a low-vision user on the Orders report
m_lv.IsZoomControlEnabled = False  ' Users can't Ctrl+scroll to change it themselves

A typical combination for a kiosk-style dashboard: set ZoomFactor once to a layout that fits your form, then set IsZoomControlEnabled = False so an accidental Ctrl+scroll during scrolling doesn't resize the page.

See Part II -> Settings and Browser Behavior for the complete property reference.

11.4 Popups

PopupMode and OpenPopupsInSameWindow

PopupMode (type LV2_POPUP_MODE, read/write) controls what happens when the page tries to open a new window — for example a link with target="_blank", or a window.open() call. It's a numeric enum: 0 = Allow, 1 = Block, 2 = SameWindow.

VBA
m_lv.PopupMode = 1   ' Block all popups — good default for a locked-down LOB screen

OpenPopupsInSameWindow (Boolean, read/write) is a separate setting that also affects how popups are navigated, forcing them to load into the same window rather than a new one. The exact interaction between the two when both are set is covered in Part II -> Settings and Browser Behavior — for most internal apps you'll only need one of them: PopupMode = 1 if you never want popups, or PopupMode = 2 / OpenPopupsInSameWindow = True if a report page opens links you want to keep inside your existing view instead of spawning a separate window.

A minimal page-side trigger, for context — an Orders report with a "Print invoice" link that would normally pop a new window:

HTML
<a href="/orders/invoice.html?id=4821" target="_blank">Print invoice</a>

With PopupMode = 1 that link simply does nothing when clicked; with PopupMode = 2 (or OpenPopupsInSameWindow = True) it navigates the existing m_lv view to the invoice page instead of opening a new window.

See Part II -> Settings and Browser Behavior for the complete property reference.

11.5 Find-in-Page

Every WebView2-based control can search the currently loaded page's text, the same way Ctrl+F works in a normal browser. This is useful for an internal report page that's just a long HTML table — a Customers or Orders listing rendered as HTML rather than paged through your own UI — where you want "find the row for Contoso" without building your own search box logic against the DOM.

StartFind, FindNext / FindPrevious, StopFind

VBA
' Start a find session for whatever the user typed into txtSearch on frmDashboard
m_lv.StartFind txtSearch.Text, False, False   ' case-insensitive, partial match

' Move between matches, e.g. from "Next" / "Previous" buttons
m_lv.FindNext
m_lv.FindPrevious

' End the session when the user closes the search bar
m_lv.StopFind False   ' False = keep the current selection, True = clear it

Caution

StopFind's parameter is easy to get backwards — False keeps the last-found selection highlighted on the page, True clears it. Decide up front which behavior your "close search" button should have.

Find state properties: FindMatchCount, FindActiveMatchIndex, IsFindActive, SuppressFindUI, FindHighlightAllMatches

VBA
Debug.Print "Matches: " & m_lv.FindMatchCount
Debug.Print "Active: " & m_lv.FindActiveMatchIndex
Debug.Print "Active session: " & m_lv.IsFindActive

m_lv.SuppressFindUI = True             ' Hide WebView2's built-in find toolbar
m_lv.FindHighlightAllMatches = True    ' Highlight every match, not just the current one

FindMatchCount and FindActiveMatchIndex are what you'd use to drive your own "Match X of Y" label next to a custom search box on frmDashboard, instead of relying on the browser's own find bar:

VBA
Private Sub txtSearch_Change()
    m_lv.StartFind txtSearch.Text, False, False
End Sub

Private Sub UpdateMatchLabel()
    If m_lv.FindMatchCount > 0 Then
        lblMatches.Caption = "Match " & m_lv.FindActiveMatchIndex & _
                              " of " & m_lv.FindMatchCount
    Else
        lblMatches.Caption = "No matches"
    End If
End Sub

Whether FindActiveMatchIndex counts from 0 or from 1 isn't spelled out in the property reference — check it against your build before assuming an offset; see Part II -> Settings and Browser Behavior for the full property reference.

SuppressFindUI = True is what makes this pattern work cleanly — without it, WebView2's own find toolbar appears on top of the page alongside whatever search UI you've built into the Access form.

See Part II -> Settings and Browser Behavior for the complete property and method reference, including Reg-Free calling conventions.

11.6 Everything Else

The properties above cover the settings an internal LOB application typically needs to touch. LiteView2 exposes a much larger set of browser-behavior settings that this chapter deliberately skips — they're documented in full in Part II -> Settings and Browser Behavior:

If you're deciding whether to disable something for a hardened deployment, start there — it's an exhaustive listing, not just the handful covered above.

Chapter 12: Downloads, Cookies and Session Data

This chapter covers three things that are easy to lump together but are managed through completely separate LiteView2 calls:

All examples below use Registered mode (m_lv As LiteView2Lib.LiteView2Ctrl), the running example for Part I. Registration-Free deployments call the same operations on the pool object instead (pool.MethodName idx, ...); Chapter 17 covers that calling convention and the pool / idx variable names used from there on.

12.1 Letting the user download a report

Say frmOrders has an Export Report button that opens a server-rendered report page, and that page offers the export as a normal download link:

HTML
<!-- served from https://reports.internal.example.com/orders/export -->
<h1>Orders Report</h1>
<p>Choose a format to download:</p>
<a id="lnkExportCsv" href="/orders/export.csv">Download CSV</a>
<a id="lnkExportPdf" href="/orders/export.pdf">Download PDF</a>

There is nothing LiteView2-specific about that HTML — it is a page that offers ordinary download links. What LiteView2-specific behavior determines is what happens when the user clicks one: whether downloads are allowed at all, where the file lands, and whether a download dialog interrupts the user.

Like the rest of the calls in this chapter, these talk to the browser, so set them up once inside WebViewReady (or later) — not Form_Load:

VBA
' Called from LiteView2Ctrl1_WebViewReady
Private Sub SetupDownloads()
    With m_lv
        .AllowDownloads = True
        .DefaultDownloadFolderPath = "C:\LiteViewReports\"
        .HiddenDownloadUI = True   ' no browser download prompt/dialog
    End With
End Sub

Private Sub cmdExportReport_Click()
    m_lv.Navigate "https://reports.internal.example.com/orders/export"
End Sub

What should happen: when the user clicks a download link on the page, the file is saved directly into C:\LiteViewReports\ with no download-progress popup, because HiddenDownloadUI is True. Setting AllowDownloads = False instead blocks every download attempt outright — useful for a kiosk-style form where you never want a file leaving the machine through the browser.

If you would rather show the browser's own download manager (progress, history, "show in folder") instead of running silently, leave HiddenDownloadUI at its default and drive the dialog yourself:

VBA
Private Sub cmdShowDownloads_Click()
    If Not m_lv.IsDownloadDialogOpen Then
        m_lv.OpenDownloadDialog
    Else
        m_lv.CloseDownloadDialog
    End If
End Sub

IsDownloadDialogOpen is read-only — use it to avoid opening a second copy of the dialog, or to decide whether you need to close it before doing something else with the control.

Caution

if you turn on silent downloads (HiddenDownloadUI = True), the user has no browser-provided indication that anything happened. Build your own confirmation (a status label, a "Report saved" message box) rather than relying on the browser to tell them.

See Part II → Downloads & Cookies for the full property list and reference details.

Dialog positioning polish

If you do show the built-in download dialog, DefaultDownloadDialogCornerAlignment, DefaultDownloadDialogMarginX, and DefaultDownloadDialogMarginY control which corner it anchors to and its offset in pixels:

VBA
m_lv.DefaultDownloadDialogCornerAlignment = 3  ' LV2_DOWNLOAD_CORNER_BOTTOM_RIGHT
m_lv.DefaultDownloadDialogMarginX = 20
m_lv.DefaultDownloadDialogMarginY = 20

These are cosmetic settings, not covered further here — see Part II → Downloads & Cookies for the corner-alignment constants.

12.2 Monitoring and controlling an in-flight download

A large export can take a while, and you may want a Pause/Resume/Cancel row on frmOrders next to the Export button. PauseDownload, ResumeDownload, and CancelDownload each take a downloadId — the same ID that LiteView2's Download* events hand you as a download starts and progresses. This chapter doesn't cover those events in detail; see Part II → Events for their exact names and parameters. What matters here is the pattern: capture the ID from the event, then use it with these three calls.

VBA
Private m_lastDownloadId As String   ' captured in a Download* event handler; see Part II -> Events

Private Sub cmdPauseDownload_Click()
    If Len(m_lastDownloadId) > 0 Then m_lv.PauseDownload m_lastDownloadId
End Sub

Private Sub cmdResumeDownload_Click()
    If Len(m_lastDownloadId) > 0 Then m_lv.ResumeDownload m_lastDownloadId
End Sub

Private Sub cmdCancelDownload_Click()
    If Len(m_lastDownloadId) > 0 Then m_lv.CancelDownload m_lastDownloadId
End Sub

What should happen: calling PauseDownload with a valid, still-active ID suspends that transfer; ResumeDownload continues it; CancelDownload stops it and discards the partial file. All three are no-ops (or errors) if the ID doesn't correspond to a download that's still in flight — which is another reason to capture the ID from the event rather than guessing at it.

See Part II → Downloads & Cookies for the method reference, and Part II → Events for how to capture downloadId in the first place.

12.3 A stuck login on the Customers portal: cookies vs. cache

Cookies are how a site remembers who's logged in. If a Customers portal your Access form embeds via LiteView2 seems to randomly "forget" that the user is signed in — or won't let a second user switch accounts — cookies and cached browsing data are where to look. All of the calls below talk to the browser and its profile, so call them once the browser is ready — from a button handler, a timer or NavigationCompleted. GetCookies and ClearBrowsingDataInTimeRange wait for the browser and fail inside WebViewReady (&H80040203).

Inspect and seed cookies for a URL:

VBA
Dim cookiesJson As String
cookiesJson = m_lv.GetCookies("https://portal.example.com")   ' JSON array: name, value, attributes

m_lv.SetCookie "sessionId", "abc123", ".example.com", "/"     ' pre-seed a session before navigating

For a "Reset Session" / "Switch User" button, these calls cover the range from a full reset down to a minimal one:

VBA
' Broadest: every cookie, or every cookie for the current profile
m_lv.ClearCookies
m_lv.ClearProfileCookies

' Targeted: a bitmask of LiteView2BrowsingDataKinds — e.g. cache + cookies together
m_lv.ClearBrowsingData 256 + 64      ' LV2_DATA_DISK_CACHE + LV2_DATA_COOKIES

' Cookies only (all time), leaving the cache and the rest of the profile alone
m_lv.ClearBrowsingData 64            ' LV2_DATA_COOKIES

Known issue in 1.0.1.0

ClearBrowsingDataInTimeRange returns without an error but clears nothing. Use ClearBrowsingData (all time) or ClearCookies instead.

What should happen: after any of these, the next navigation to a site that was tracking a session via cookies treats the browser as a fresh, logged-out visitor — exactly what a "Reset Session" button needs. ClearCache alone (m_lv.ClearCache) clears only cached page resources, leaving cookies and everything else in the profile untouched — reach for it when the goal is freeing disk space, not resetting a login. ClearBrowsingData 16384 (LV2_DATA_ALL_PROFILE) wipes the entire profile — use it deliberately, not as a casual session reset; for a stuck login, ClearCookies/ClearProfileCookies or the targeted bitmask above is the better tool.

Note

The source material doesn't spell out the exact scope difference between ClearCookies and ClearProfileCookies beyond the wording above — see Part II → Downloads & Cookies for the precise distinction, the full LiteView2BrowsingDataKinds bitmask table, and every other data-kind constant.

12.4 Choosing the right tool

A quick summary of which call to reach for:

SituationCall
Stop the user downloading files at allAllowDownloads = False
Save reports without a download popupHiddenDownloadUI = True + DefaultDownloadFolderPath
Let the user manage downloads themselvesOpenDownloadDialog / CloseDownloadDialog / IsDownloadDialogOpen
Pause/resume/cancel one specific downloadPauseDownload / ResumeDownload / CancelDownload downloadId
Inspect what a site has stored for a loginGetCookies
Pre-seed a session cookieSetCookie
Reset a stuck login, minimal blast radiusClearCookies / ClearProfileCookies or ClearBrowsingData with LV2_DATA_COOKIES
Free disk space used by cached pagesClearCache
Full profile resetClearBrowsingData LV2_DATA_ALL_PROFILE

Chapter 13: Printing, PDF and Capture

This chapter covers two things Access and VBA developers ask for constantly: saving whatever LiteView2 is currently showing as a PDF, and grabbing a screenshot of it. From there it covers letting the user print through the normal system dialogs, driving print output from code without a dialog, and checking ahead of time whether the runtime on a given machine even supports these features.

Everything here operates on the page currently loaded in the control — there is no separate "report generator." If m_lv is showing a sales report page, PrintToPdf turns that page into a PDF. If it's showing a dashboard, CaptureScreenshot turns that into a PNG.

13.1 Saving the current report as PDF

Say frmSalesReport hosts m_lv, which is displaying a sales report page — a plain HTML table driven by tblSales, with an on-screen toolbar you don't want in the printed output:

HTML
<!-- SalesReport.html — loaded into the LiteView2 control on frmSalesReport -->
<style>
  .toolbar { margin-bottom: 12px; }
  @media print {
    .toolbar { display: none; }   /* hide the on-screen buttons in print/PDF output */
  }
</style>

<div class="toolbar">
  <button onclick="location.reload()">Refresh</button>
</div>

<table id="reportTable">
  <thead><tr><th>Order ID</th><th>Customer</th><th>Total</th></tr></thead>
  <tbody>
    <!-- rows populated from tblSales -->
  </tbody>
</table>

A command button on the form saves that report to a timestamped PDF on the desktop:

VBA
Private Sub cmdSaveReportPdf_Click()
    Dim path As String
    path = Environ("USERPROFILE") & "\Desktop\SalesReport_" & _
           Format(Now(), "yyyymmdd_hhnnss") & ".pdf"

    m_lv.PrintToPdf path
End Sub

Private Sub LiteView2Ctrl1_PrintToPdfCompleted(ByVal filePath As String, ByVal success As Boolean)
    If success Then MsgBox "Report saved.", vbInformation
End Sub

What should happen: LiteView2 renders the currently loaded page to the PDF at path, and once the file is written the PrintToPdfCompleted event fires on m_lv so you know it's safe to tell the user the report is ready.

Caution

Reg-Free mode has no completion event. pool.PrintToPdf idx, path starts the same PDF write, but it is fire-and-forget: there is no PrintToPdfCompleted to catch. Check Dir(path) <> "" the next time the user does something (closes the form, clicks a "Done" button, etc.), or, if you need a real result signal, wrap the call so the browser process can call back into a host object you supply. Chapter 17 covers the Reg-Free pool/idx pattern in full.

VBA
' Reg-Free — no completion event, so poll for the file on the next action:
pool.PrintToPdf idx, path
' ... later, e.g. in the button that closes the report form:
If Dir(path) <> "" Then
    MsgBox "Report saved."
End If

See Part II -> Print & Capture for the full PrintToPdf reference entry.

13.2 Capturing the current dashboard

The same idea applies to a screenshot. Say frmDashboard hosts m_lv showing a live dashboard page:

HTML
<!-- Dashboard.html — loaded into the LiteView2 control on frmDashboard -->
<div id="dashboard">
  <div class="kpi-card">Total Sales<br><strong>$482,910</strong></div>
  <div class="kpi-card">Open Orders<br><strong>37</strong></div>
</div>
VBA
Private Sub cmdCaptureDashboard_Click()
    Dim path As String
    path = Environ("USERPROFILE") & "\Desktop\Dashboard_" & _
           Format(Now(), "yyyymmdd_hhnnss") & ".png"

    m_lv.CaptureScreenshot path
End Sub

Private Sub LiteView2Ctrl1_CaptureScreenshotCompleted(ByVal filePath As String, ByVal success As Boolean)
    If success Then MsgBox "Dashboard captured.", vbInformation
End Sub

What should happen: a PNG of the dashboard as currently rendered appears at path, and CaptureScreenshotCompleted fires on m_lv when it's done.

The Reg-Free caveat from 13.1 applies here too, with no differences: pool.CaptureScreenshot idx, path is fire-and-forget, so check Dir(path) <> "" on the next user action rather than waiting for an event.

See Part II -> Print & Capture for the full CaptureScreenshot reference entry.

13.3 Letting the user print or save through the system dialogs

For a straight "print this" or "save this" button, three members hand off to Windows' own dialogs instead of doing the work silently.

PrintPage — silent print to the default printer

VBA
Private Sub cmdPrintReport_Click()
    m_lv.PrintPage
End Sub

This sends the current page straight to the default printer with no dialog. Registration-Free mode has no equivalent silent call — its documented substitute is ShowPrintDialog (pool.ShowPrintDialog idx), so a Reg-Free "print" button always shows the picker rather than printing silently. Chapter 17 covers the pool/idx pattern.

ShowPrintDialog — the system print dialog

VBA
Private Sub cmdPrint_Click()
    m_lv.ShowPrintDialog
End Sub

This opens the normal Windows print dialog for the current page, letting the user pick a printer, copies, and so on. Reg-Free: pool.ShowPrintDialog idx.

ShowSaveAsDialog — the system Save As dialog

VBA
Private Sub cmdSaveAs_Click()
    m_lv.ShowSaveAsDialog
End Sub

This opens the standard Save As dialog for the current page. Reg-Free: pool.ShowSaveAsDialog idx.

See Part II -> Print & Capture for the reference entries on all three.

13.4 Printing and PDF export without a dialog

PrintWithSettings and PrintToPdfWithSettings skip the dialog entirely: you set the properties you care about on m_lv, then call the method. Every print-related property behaves the same way — read it like any other property, set it, and it stays in effect until you change it again.

Landscape, background graphics included, straight to the printer:

VBA
Private Sub cmdPrintReportLandscape_Click()
    m_lv.PrintOrientation = 1          ' LV2_PRINT_ORIENTATION: 0=Portrait, 1=Landscape
    m_lv.PrintShouldPrintBackgrounds = True
    m_lv.PrintWithSettings
End Sub

Landscape with tight margins, straight to a PDF file:

VBA
Private Sub cmdSaveReportPdfNarrow_Click()
    m_lv.PrintOrientation = 1
    m_lv.PrintMarginTop = 0.25
    m_lv.PrintMarginBottom = 0.25
    m_lv.PrintToPdfWithSettings Environ("USERPROFILE") & "\Desktop\Report.pdf"
End Sub

Neither call shows a dialog, and the source doesn't document a completion event for either one in Registered mode the way it does for PrintToPdf and CaptureScreenshot — treat the call as returning once printing/writing has been kicked off.

Reg-Free code sets and reads the same properties through paired Get<Name>/Set<Name> calls that take the browser index instead of plain property syntax, e.g. pool.SetPrintOrientation idx, 1 and pool.GetPrintOrientation idx, orient. Chapter 17 covers that pattern; the shape is identical for every property below.

You are not limited to the two properties shown above. All of these follow the same set-property-then-call pattern and are read/write on m_lv:

PropertyTypeNotes
PrintOrientationLV2_PRINT_ORIENTATION0 = Portrait, 1 = Landscape
PrintScaleFactorDoubledefault 1.0
PrintMarginTop / PrintMarginBottom / PrintMarginLeft / PrintMarginRightDoubleinches
PrintPageWidth / PrintPageHeightDoubleinches
PrintShouldPrintBackgroundsBooleanprint background graphics
PrintShouldPrintSelectionOnlyBooleanprint only the current selection
PrintShouldPrintHeaderAndFooterBooleanprint header/footer
PrintHeaderTitleStringcustom header title
PrintFooterUriStringcustom footer URI
PrintCopiesLongnumber of copies
PrintPagesPerSideLongN-up printing
PrintPageRangesStringe.g. "1-3,5,7"

See Part II -> Print & Capture for the full reference entry — type, default, and both calling forms — for each of these properties, plus PrintWithSettings and PrintToPdfWithSettings themselves.

13.5 Checking capability before you offer the feature

Not every runtime a customer has installed supports every capability. HasPrintToPdf and HasCapturePreview let you check before you show a "Save as PDF" or "Capture" button at all, rather than letting the user click it and get nothing.

VBA
If m_lv.HasPrintToPdf Then
    cmdSaveReportPdf.Enabled = True
Else
    cmdSaveReportPdf.Enabled = False
End If

Debug.Print "Screenshot support: " & m_lv.HasCapturePreview

Both are read-only Boolean properties. Reg-Free reads them the same way as the other properties in this chapter, but as a function call that takes the index: pool.HasPrintToPdf(idx) and pool.HasCapturePreview(idx).

Run this check once when the form loads (or the control finishes initializing — see Chapter 4) and use the result to enable or disable the relevant buttons, rather than checking it on every click.

13.6 Debugging aside: OpenTaskManagerWindow

OpenTaskManagerWindow opens the browser's own task manager window — useful while you're troubleshooting a page that's hanging or eating memory, not something you'd wire up to end-user UI.

VBA
m_lv.OpenTaskManagerWindow

Reg-Free: pool.OpenTaskManagerWindow idx.

Chapter 14: Authentication and Custom Web Requests

Every navigation so far in this book has been a plain GET: m_lv.Navigate "https://...". Two situations come up in real applications that a plain GET doesn't cover. First, you sometimes need to send data with the navigation itself — a POST body and headers, the way an HTML form submits. Second, some sites you navigate to are protected by HTTP authentication rather than a login page, and you need to supply credentials instead of waiting for a browser prompt. A third, more advanced capability — watching or answering the page's own requests before they reach the network — is covered at the end of this chapter, after the two common cases.

14.1 Sending a POST Request with Custom Headers

The simple case: NavigateWithWebResourceRequest

Say frmCustomers collects a new customer's name and email, and instead of writing to a local table you need to submit that data to an internal web API and show whatever confirmation page it returns.

VBA
Dim postBody As String
postBody = "name=" & Me.txtCustomerName & "&email=" & Me.txtCustomerEmail

m_lv.NavigateWithWebResourceRequest _
    "https://api.example.com/submit", _
    "POST", _
    postBody, _
    "Content-Type: application/x-www-form-urlencoded"

What should happen: LiteView2 issues the POST with the body and header you supplied, and navigates to whatever page the server sends back — the same end result as if an HTML <form method="post"> on the page had been submitted, except you built it entirely from VBA.

Registration-Free calls the same operation through the pool object: pool.NavigateWithWebResourceRequest idx, url, method, postData, headers. Chapter 17 covers the pool/idx pattern used for Reg-Free code throughout this book.

See Part II → Web Resource Requests for the full parameter reference.

A handle-based alternative: CreateWebResourceRequest and NavigateWithCustomRequest

NavigateWithWebResourceRequest builds and navigates in a single call. CreateWebResourceRequest splits that into two steps: build a request object first — getting back a Long handle — then navigate with it separately. Reach for this form when the request needs to be assembled in one place and fired from another, for example approving an order from a toolbar button after the request body was already put together when the order loaded.

VBA
Dim hReq As Long
hReq = m_lv.CreateWebResourceRequest("POST", "https://api.example.com/submit", _
    "Content-Type: application/json", "{""OrderID"":1042,""Status"":""Approved""}")

m_lv.NavigateWithCustomRequest hReq

CreateWebResourceRequest takes method, URL, header string, and POST body, in that order, and returns the handle. The same call works for a GET carrying only a header, with no body:

VBA
Dim hReq As Long
hReq = m_lv.CreateWebResourceRequest("GET", "https://api.example.com/data", _
    "Authorization: Bearer token123", "")

Registration-Free: pool.CreateWebResourceRequest(idx, method, url, headers, postData) returns the handle, and pool.NavigateWithCustomRequest idx, hReq performs the navigation.

Blocking until the navigation completes: NavigateWithWebResourceRequestSync

Both forms above return immediately — the navigation happens asynchronously, and you'd normally learn it finished from the NavigationCompleted event. When your code needs the result before it can continue — a report routine that submits a request and then immediately has to read the page that comes back — use the synchronous variant with a handle from CreateWebResourceRequest:

VBA
Dim hReq As Long
hReq = m_lv.CreateWebResourceRequest("POST", "https://api.example.com/data", _
    "Content-Type: application/json", "{""key"":""value""}")

m_lv.NavigateWithWebResourceRequestSync hReq
' Execution resumes here when the next navigation completes (see the caution below).

Caution

this call blocks your VBA code until NavigationCompleted or SynchronousTimeOut (messages keep pumping, so the UI stays responsive). Use it for short, predictable internal requests — not for navigating to arbitrary external pages where load time isn't under your control. Call it from ordinary code (a button, a timer) or from a notification event such as NavigationCompleted; inside WebViewReady, NavigationStarting, the other inline events and host-object methods it fails at once with &H80040203 and starts no navigation (use NavigateWithCustomRequest there). Known issue in 1.0.1.0: the wait ends at the next NavigationCompleted, whichever navigation it belongs to. If a navigation is already in progress, the call can return when that other navigation completes, before its own page has loaded. Use Navigate + NavigationCompleted when navigations can overlap.

Registration-Free: pool.NavigateWithWebResourceRequestSync idx, hReq.

See Part II → Web Resource Requests for more on the synchronous variant and the request handle's lifetime.

14.2 Authentication

The most common case: some internal sites — a reporting server, an internal dashboard — sit behind HTTP Basic Authentication rather than a login form. Rather than waiting for the browser to prompt, check support and register credentials for a URI pattern before you navigate:

VBA
If m_lv.HasAuthenticationSupport Then
    m_lv.SetBasicAuthCredentials "https://api.example.com/*", "username", "password"
End If
m_lv.Navigate "https://api.example.com/dashboard"

' Later, to remove the stored credentials:
m_lv.ClearBasicAuthCredentials

What should happen: any request whose URL matches the pattern is authenticated with the stored credentials automatically; no prompt appears. HasAuthenticationSupport is a capability check worth making first, since it's read-only and tells you whether the rest of this section applies to the current environment at all.

Registration-Free: the same three calls, indexed — pool.SetBasicAuthCredentials idx, uriPattern, username, password, pool.ClearBasicAuthCredentials idx, pool.HasAuthenticationSupport(idx).

A couple of related mechanisms exist for less common cases, covered in full in Part II → Authentication: the BasicAuthenticationRequested event lets you react at the moment a site actually challenges for credentials, instead of pre-registering them; AllowSingleSignOnUsingOSPrimaryAccount = True lets an intranet site that supports Windows Integrated Authentication sign the user in silently with their Windows account, with no credential prompt at all.

14.3 Intercepting and Responding to Requests (Advanced)

Everything up to this point handles requests your code initiates. The page itself also makes requests — for its own scripts, images, and API calls — and LiteView2 lets you see, block, or answer those before they reach the network. Most applications never need this; reach for it when you're building something like a tracker/ad blocker, a request auditor, or a page that must be prevented from calling out to certain domains.

Defining what to intercept: filters

A filter is a URL pattern plus a resource-type code. A request only becomes visible to interception once it matches an active filter — matching by itself does not block anything (see the next section).

VBA
' 0 = all resource types
m_lv.AddWebResourceRequestedFilter "*.doubleclick.net*", 0
m_lv.AddWebResourceRequestedFilter "*.googlesyndication.com*", 0

' 3 = Image — block only images from this domain
m_lv.AddWebResourceRequestedFilter "*.ads.example.com*", 3

Remove one filter, or clear all of them:

VBA
m_lv.RemoveWebResourceRequestedFilter "*.doubleclick.net*", 0
m_lv.ClearAllWebResourceRequestedFilters

Registration-Free: pool.AddWebResourceRequestedFilter idx, pattern, resourceType, pool.RemoveWebResourceRequestedFilter idx, pattern, resourceType, pool.ClearAllWebResourceRequestedFilters idx.

See Part II → Web Resource Interception for the full resource-type code list.

Turning interception into blocking

Filters alone only mark which requests are intercepted. To actually block the matches, enable blocking:

VBA
m_lv.AddWebResourceRequestedFilter "*.ads.example.com*", 0
m_lv.SetWebResourceBlocking True

Check whether blocking is currently on, and see which filters are active, as a JSON array:

VBA
Debug.Print "Blocking enabled: " & m_lv.IsWebResourceBlockingEnabled
Debug.Print m_lv.GetWebResourceRequestedFilters

Registration-Free: pool.SetWebResourceBlocking idx, True, pool.IsWebResourceBlockingEnabled(idx), pool.GetWebResourceRequestedFilters(idx).

Counting blocked requests

For a dashboard tile showing how much has been blocked in the current session:

VBA
Debug.Print "Blocked: " & m_lv.BlockedRequestCount
m_lv.ResetBlockedRequestCount

Registration-Free: the property becomes a method — pool.GetBlockedRequestCount(idx) — and resetting is pool.ResetBlockedRequestCount idx.

Serving a synthetic response: CreateWebResourceResponse

Intercepting a request doesn't limit you to blocking it silently — you can hand back your own response body, status code, and headers. This is how you'd serve an actual "403 Forbidden" page instead of a broken image or a blank result:

VBA
Dim hResp As Long
hResp = m_lv.CreateWebResourceResponse("<h1>Blocked</h1>", 403, "Forbidden", _
    "Content-Type: text/html")

This is meant to be built inside a WebResourceRequested handler (next section) — that's where you supply the response object for the request you're answering.

Registration-Free: pool.CreateWebResourceResponse(idx, body, statusCode, statusText, headers).

Watching requests and responses

Two events cover interception at the request and response stages:

VBA
m_lv.EnableWebResourceResponseTracking True

Registration-Free: pool.EnableWebResourceResponseTracking idx, True.

See Part II → Events for both handler signatures, and Part II → Web Resource Interception for how the request and response objects are represented.

14.4 Proxy and Certificate Settings

Three related properties round out this chapter. ProxyServer and ProxyBypassList (both String, read/write, and both pre-init only — set before the control initializes, not after) configure an outbound proxy and its bypass list. IgnoreCertificateErrors (Boolean, read/write) suppresses SSL certificate validation and is documented for development and testing only; leaving it True in a production deployment defeats certificate checking entirely. Registration-Free exposes the same settings as pool.SetProxyServer/pool.GetProxyServer, pool.SetProxyBypassList, and pool.SetIgnoreCertificateErrors, each taking idx. See Part II → Proxy and Network Settings for the full configuration reference.

Chapter 15: Multiple Browsers, Profiles and Sessions

Every example so far has used one LiteView2Ctrl on one form. That covers a large share of real Access and VB6 applications — a single embedded browser showing a report, a dashboard, or a document viewer. This chapter is for the cases where one browser is not enough: comparing two customer sessions side by side, keeping a login isolated from the rest of the app, or managing a bank of report panels that get created and torn down as the user navigates.

15.1 The Registered-Mode Ceiling: One Control, One Browser

Say this plainly, because it trips people up: Registered Mode is one ActiveX control instance per form. There is no multi-browser pool concept in Registered Mode. m_lv is one browser. If you drop a second LiteView2Ctrl on the form, you get a second, completely independent control — that works, but it does not scale past a handful of fixed, designed-at-build-time panels, and it does not give you dynamic profiles, parking, or runtime-created instances.

If what you actually need is several independent browser instances — created and destroyed at runtime, each with its own login, each addressable by an index — that is Reg-Free Mode. Reg-Free gives you a pool object (obtained from GetPool(), per the shared-module pattern used throughout this book) and every browser you create through it comes back as an integer index. The rest of this chapter previews the pool members you need for the multi-browser, multi-profile, multi-panel scenario. Chapter 17 covers Reg-Free deployment — registration, the DLL layout, and the pool lifecycle — in full.

For the rest of this chapter, pool (As Object, from GetPool()) and idx (As Long, the index returned by a create call) are the variable names used throughout, matching the convention used from Chapter 17 onward.

15.2 Creating Independent Browser Instances

Suppose frmDashboard in a support-desk Access application needs two browsers open at once: one showing an internal orders report, one showing the external customer portal. Each needs to exist, resize, and close independently of the other — that's the case for two pool-created instances.

VBA
Dim pool As Object
Dim idxReport As Long
Dim idxPortal As Long

Set pool = GetPool()   ' shared module: handles ActivateLicense + pool setup, see Chapter 17

' A browser in its own raw window, positioned and sized explicitly
idxReport = pool.Create(Me.hWnd, "https://intranet.example.com/orders/report", 10, 10, 800, 600)

' A second, independent browser embedded directly inside a Frame control on the form
idxPortal = pool.CreateInControl("about:blank", Me.FraPortal)

Create opens a browser positioned against a window handle you supply (Me.hWnd here, so it's a child window of the Access form) at the given x, y, width, and height. CreateInControl skips the manual positioning and embeds the browser directly inside a Frame control you've already placed on the form — the same way m_lv sits inside the form in Registered Mode, except now you can have as many of them as you want, and each one hands back its own idx.

Both calls return Long — the index for that browser. Most other pool methods in this chapter that act on a specific browser take that index as their first (or only) parameter to say which browser it applies to; a few — like DestroyAllParked, GetParkedBrowserCount, GetBrowserCount, and the runtime-detection calls in 15.6 — apply to the pool as a whole and take no index at all.

What should happen: two browsers appear — one in the raw window area, one inside FraPortal — each navigable and destroyable independently through idxReport and idxPortal.

See Part II → Pool-Only: Create / CreateInControl for the full parameter reference.

15.3 Reusable Profiles for Separate Sessions and Logins

An index alone gives you separate browser instances, but by default they can still share the same underlying browsing data. When two panels need genuinely isolated sessions — for example, a support supervisor comparing what two different customer accounts see when logged into the same portal — you create each browser against a named profile.

VBA
Dim idxCustomerA As Long
Dim idxCustomerB As Long

idxCustomerA = pool.CreateWithProfile(Me.hWnd, "https://portal.example.com/login", 0, 0, 800, 600, "CustomerA")
idxCustomerB = pool.CreateInControlWithProfile("https://portal.example.com/login", Me.FraCustomerB, "CustomerB")

' A private profile - use for a one-off check you don't want persisted to disk under any profile name
Dim idxAudit As Long
idxAudit = pool.CreateWithProfileInPrivate(Me.hWnd, "https://portal.example.com/login", 0, 0, 800, 600, "AuditCheck")

CreateWithProfile is the raw-window form of Create with a profile name added as the last argument; CreateInControlWithProfile is the same idea for CreateInControl. Browsers created against the same profile name share cookies, cache, and login state; browsers on different profile names do not — that's what lets idxCustomerA and idxCustomerB stay logged in as two different customers at the same time without one login stomping the other. CreateWithProfileInPrivate still takes a profile name but creates the session as a private/in-private browsing context.

Once a browser exists, you can look its profile back up, and clear that profile's stored browsing data:

VBA
Debug.Print pool.GetProfileName(idxCustomerA)   ' "CustomerA"
Debug.Print pool.GetProfilePath(idxCustomerA)    ' folder on disk backing that profile

pool.ClearProfileBrowsingData idxCustomerA, 16384   ' 16384 is a data-category flag - see Part II for the full flag list
pool.ClearProfileBrowsingDataAll idxCustomerA        ' clear everything for this profile

What should happen: idxCustomerA and idxCustomerB can be logged into the customer portal as two different accounts simultaneously, and GetProfileName/GetProfilePath let you confirm which on-disk profile a given index is actually using before you clear anything.

See Part II → Pool-Only: Profile Creation and Pool-Only: Profile Management for the full parameter and flag reference.

15.4 Moving and Resizing Browsers Across Panels

A dashboard often needs to move a browser between panels at runtime — collapsing one panel and expanding another, or promoting an embedded panel out into its own popup window. In Reg-Free Mode this is direct pool manipulation by index:

VBA
pool.Resize idxPortal, 0, 0, 1024, 768
pool.EmbedInControl idxPortal, Me.FraOtherPanel
pool.Reparent idxPortal, newHwnd, 0, 0, 800, 600

Resize changes the browser's width and height in place. EmbedInControl moves an existing browser (already created, identified by idx) into a different Frame control — useful when the user switches which tab or panel should host it. Reparent moves it to a different raw window handle entirely, which is how you'd promote an embedded panel into its own top-level window.

Registered Mode's Equivalent

Registered Mode has no Reparent/EmbedInControl, because there's only ever one browser (m_lv) to move — but that one browser can still be relocated into an external window handle, resized, moved, and closed:

VBA
m_lv.EmbedInHwnd CLngLng(hwndParent), 800, 600
m_lv.EmbedInHwndByLong CLng(hwndParent), 800, 600   ' VB6 compat

m_lv.ResizeEmbedded 1024, 768
m_lv.MoveEmbedded 100, 50
m_lv.CloseEmbedded

EmbedInHwnd takes a raw Win32 window handle rather than a Frame control — useful when the target isn't a VB6/Access control at all, just a window handle you obtained some other way. EmbedInHwndByLong is the same call with a Long handle parameter for VB6 compatibility. ResizeEmbedded, MoveEmbedded, and CloseEmbedded then manage that one embedded browser. The distinction to keep straight: these Registered-Mode calls relocate and resize the single existing browser — they do not create a second one.

See Part II → Pool-Only: Resize / EmbedInControl / Reparent and → EmbedInHwnd / EmbedInHwndByLong for the full reference.

15.5 Tearing Down Browsers at Scale

A dashboard that creates report panels on demand also needs to close them without leaking browser processes. The pool gives you three ways to remove a browser, plus bulk cleanup and counters:

VBA
pool.Destroy idxPortal              ' Async destroy - returns immediately
pool.DestroySync idxAudit           ' Sync destroy - blocks until fully torn down
pool.Park idxCustomerA              ' Hide for reuse, instead of destroying
pool.DestroyAllParked               ' Clean up every parked browser at once

Debug.Print pool.GetParkedBrowserCount
Debug.Print pool.GetBrowserCount

Destroy tears a browser down asynchronously — the call returns before teardown necessarily finishes. DestroySync blocks until the browser is fully gone, which matters if you need certainty before proceeding (for example, right before the Access application closes). Park is the cheaper alternative to destroying: it hides the browser instead of tearing it down, so if the user comes back to that panel you can reuse it instead of paying browser-startup cost again. DestroyAllParked reclaims every parked browser in one call. GetParkedBrowserCount and GetBrowserCount let you track how many browsers are parked versus live at any point — useful for a diagnostic screen or before deciding whether to park or destroy.

Caution

DestroySync blocks the calling thread until teardown completes. Call it from an ordinary event handler (a button click, Form_Unload) the way the examples in this book do — not from inside a callback the browser's own message pump is waiting on (a WebMessageReceived-style handler or similar). If you're unsure whether a given call site qualifies, prefer the async Destroy and confirm completion via GetBrowserCount instead.

What should happen: after DestroyAllParked, GetParkedBrowserCount returns 0; GetBrowserCount reflects only the browsers still actually live.

See Part II → Pool-Only: Destroy / DestroySync / Park for the full reference.

15.6 Checking the WebView2 Runtime Before You Create Anything

Before creating any browser on a machine of unknown configuration, check that the WebView2 Runtime is actually present:

VBA
If pool.IsWebView2RuntimeInstalled Then
    Debug.Print "Version: " & pool.GetWebView2RuntimeVersion
    Debug.Print "Path: " & pool.GetWebView2RuntimePath
Else
    MsgBox "The WebView2 Runtime is not installed on this machine.", vbExclamation
End If

IsWebView2RuntimeInstalled is the guard to run first — every Create/CreateInControl/CreateWithProfile call in this chapter depends on that runtime being present. GetWebView2RuntimeVersion and GetWebView2RuntimePath are useful once you know it's installed, for logging or for diagnosing a version-specific issue on a deployed machine.

See Part II → Pool-Only: Runtime Detection for the full reference.

15.7 Listing Loaded Browser Extensions

For a given browser index, you can list the extensions currently loaded in that browser's profile:

VBA
Debug.Print pool.GetBrowserExtensionList(idxCustomerA)

See Part II → Pool-Only: GetBrowserExtensionList for the full reference.

15.8 Licensing Multiple Browsers

One thing you do not need to do per browser: activate the license. ActivateLicense is process-wide — one successful call activates every LiteView2 browser created afterwards in that Access (or Office) session, so idxReport, idxPortal, idxCustomerA, and idxCustomerB all inherit the same activation with no extra work.

See Chapter 21 for the full licensing story, including trial state and activation failure handling.

Chapter 16: Building a Real Access/VBA/VB6 LiteView2 Screen

The previous chapters each covered one piece of LiteView2 in isolation: loading a page, pushing data into it, calling from JavaScript back into VBA, and closing down cleanly. This chapter puts those pieces together into one screen you could actually ship — an Access form that shows open orders in an HTML dashboard, lets the user mark an order shipped from the page, and updates the real Access data when they do.

The example uses Registered Mode (m_lv As LiteView2Lib.LiteView2Ctrl) throughout, since that's this cookbook's default. One section near the end shows the single documented wiring difference for VB6 and Excel UserForms.

16.1 The scenario

Each step below shows the piece in isolation with what should happen when it runs. Section 16.9 gives the complete, consolidated listing.

16.2 Loading the dashboard page

VBA
Option Compare Database
Option Explicit

Private m_lv As LiteView2Lib.LiteView2Ctrl

Private Sub Form_Load()
    Set m_lv = Me.LiteView2Ctrl1.Object
End Sub

Private Sub LiteView2Ctrl1_WebViewReady()
    m_lv.SetLocalContentRoot CurrentProject.Path
    m_lv.Navigate "https://lv2.example/customers_dashboard.html"
End Sub

This is the same virtual-host Navigate pattern from Chapter 2/3 — nothing new here. Opening frmCustomers should show a blank dashboard page with an empty orders table; the data arrives in the next step, once the page has actually finished loading.

16.3 Pushing the open orders once the page is ready

We don't push data immediately after calling Navigate — the page hasn't loaded yet. We wait for the control's NavigationCompleted event, which Access wires up automatically because the control on the form is named LiteView2Ctrl1:

VBA
Private Sub LiteView2Ctrl1_NavigationCompleted(ByVal url As String, ByVal success As Boolean)
    PushOrdersToPage
End Sub

Private Sub PushOrdersToPage()
    Dim rs As DAO.Recordset
    On Error GoTo ErrH

    Set rs = CurrentDb.OpenRecordset( _
        "SELECT OrderID, CustomerName, OrderDate, Status " & _
        "FROM tblOrders WHERE Status <> 'Shipped'", dbOpenSnapshot)

    m_lv.PushRecordset rs, "renderOrders"

    rs.Close
    Set rs = Nothing
    Exit Sub

ErrH:
    MsgBox "Could not load orders: " & Err.Description, vbExclamation
End Sub

PushRecordset (Chapter 8) hands the open-order rows to the page; the JavaScript side you register there is what actually turns them into HTML. Opening the form should populate the table within a moment of the page appearing, with one row per open order.

See Part II → Recordset Transfer for every PushRecordset overload and column-mapping option.

16.4 Rendering the rows in JavaScript

The page side is plain HTML and JavaScript — the same table-building code you'd write for any local page:

HTML
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Customer Orders</title>
</head>
<body>
  <h1>Open Orders</h1>
  <div id="divResults-6"></div>

  <script>
    function renderOrders(rows) {
      var container = document.getElementById('divResults');
      var html = '<table border="1" cellpadding="4">' +
        '<thead><tr><th>Order</th><th>Customer</th><th>Date</th><th>Status</th><th></th></tr></thead><tbody>';
      rows.forEach(function (r) {
        html += '<tr data-order-id="' + r.OrderID + '">' +
          '<td>' + r.OrderID + '</td>' +
          '<td>' + r.CustomerName + '</td>' +
          '<td>' + r.OrderDate + '</td>' +
          '<td class="status">' + r.Status + '</td>' +
          '<td><button onclick="shipOrder(' + r.OrderID + ')">Mark Shipped</button></td>' +
          '</tr>';
      });
      html += '</tbody></table>';
      container.innerHTML = html;
    }
  </script>
</body>
</html>

renderOrders is the receiving function on the divResults target that Chapter 8 has you register against PushRecordset; once it runs, the page shows one table row per open order with a "Mark Shipped" button in the last column.

16.5 Calling back into VBA from the "Mark Shipped" button

Clicking the button needs to reach VBA with the OrderID of the row that was clicked. That's the host object pattern from Chapter 5: a VBA class exposing a method, registered with the control so the page can call it directly.

VBA
' Class module: CHostBridge
Option Explicit

Private m_lv As LiteView2Lib.LiteView2Ctrl

Public Sub Init(ByVal ctrl As LiteView2Lib.LiteView2Ctrl)
    Set m_lv = ctrl
End Sub

Public Sub MarkOrderShipped(ByVal OrderID As Long)
    ' business logic lives here — see 16.6
End Sub
VBA
' Form module: extends Form_Load and WebViewReady from 16.2
Private m_HostBridge As CHostBridge

Private Sub Form_Load()
    Set m_lv = Me.LiteView2Ctrl1.Object
    Set m_HostBridge = New CHostBridge
    m_HostBridge.Init m_lv
End Sub

Private Sub LiteView2Ctrl1_WebViewReady()
    m_lv.SetLocalContentRoot CurrentProject.Path
    m_lv.AreHostObjectsAllowed = True
    m_lv.AddHostObjectToScript "hostBridge", m_HostBridge
    m_lv.Navigate "https://lv2.example/customers_dashboard.html"
End Sub
HTML
<script>
  function shipOrder(orderId) {
    window.chrome.webview.hostObjects.hostBridge.MarkOrderShipped(orderId);
  }
</script>

Clicking "Mark Shipped" should call MarkOrderShipped in VBA with the order's ID, with no page navigation and no round trip through Access UI. Host object calls from JavaScript are asynchronous from the page's point of view, so don't assume the confirmation is back before the click handler returns — that's what step 16.6 sends explicitly.

See Part II → Host Objects & Script Bridging for the full AddHostObjectToScript registration contract.

16.6 Updating Access data and confirming back to the page

MarkOrderShipped does the real work: update tblOrders with DAO, then tell the page the row changed so it can update itself without a fresh PushRecordset.

VBA
Public Sub MarkOrderShipped(ByVal OrderID As Long)
    Dim rs As DAO.Recordset
    On Error GoTo ErrH

    Set rs = CurrentDb.OpenRecordset( _
        "SELECT OrderID, Status FROM tblOrders WHERE OrderID = " & OrderID, _
        dbOpenDynaset)

    If Not rs.EOF Then
        rs.Edit
        rs!Status = "Shipped"
        rs.Update
    End If
    rs.Close
    Set rs = Nothing

    m_lv.ExecuteScriptAsync "updateOrderRow(" & OrderID & ", 'Shipped');"
    Exit Sub

ErrH:
    ' swallow here — a failed confirmation shouldn't crash the page's click handler
End Sub
HTML
<script>
  function updateOrderRow(orderId, status) {
    var row = document.querySelector('tr[data-order-id="' + orderId + '"]');
    if (row) {
      row.querySelector('.status').textContent = status;
    }
  }
</script>

ExecuteScriptAsync (Chapter 4) runs updateOrderRow(...) directly in the page. After clicking "Mark Shipped", the row's Status cell should change to "Shipped" in place, and tblOrders on disk now reflects it too.

PostWebMessageAsJson (Chapter 6) is the other option for this same step: post {"type":"orderShipped","orderId":123} from VBA and have the page listen with window.chrome.webview.addEventListener('message', ...) instead of exposing a named JS function. Either gets the confirmation to the page; ExecuteScriptAsync is simpler when you already know which function to call, PostWebMessageAsJson is preferable when several unrelated pieces of the page need to react to the same event.

See Part II → Script Execution & Messaging for both APIs in full, including error handling on the JS side.

16.7 Event Wiring Outside Access: WithEvents

Everything above assumes an Access form, where dropping LiteView2Ctrl1 onto the form gives you Private Sub LiteView2Ctrl1_NavigationCompleted(ByVal url As String, ByVal success As Boolean) and the rest of the design-time event stubs for free, and where Me.LiteView2Ctrl1.Object is the documented way to unwrap Access's own control wrapper into a typed reference (Chapter 2 explains why .Object is needed there).

The Cookbook also documents a second, explicit event-wiring pattern that works with LiteView2 as a plain COM object, independent of any particular host: declare the reference with WithEvents, and VBA generates Private Sub <VariableName>_<EventName> handlers keyed to that variable name instead of a control's instance name.

VBA
Private WithEvents m_lv As LiteView2Lib.LiteView2Ctrl

Private Sub m_lv_NavigationCompleted(ByVal url As String, ByVal success As Boolean)
    If success Then PushOrdersToPage
End Sub

This is a real, working pattern for the control's events. What this source material does not establish is whether a design-time-placed LiteView2 control on a VB6 Form or an Excel UserForm also generates instance-named event stubs the way Access does, or whether WithEvents is the only route to its events in those hosts — that is host-specific IDE behavior this Cookbook doesn't test or document either way. The same caution applies to acquiring the reference (whether .Object is needed outside Access) and to the project-path equivalent of CurrentProject.Path in each host (VB6: App.Path; Excel: ThisWorkbook.Path) — do not assume Access's syntax carries over unchanged. Treat WithEvents as a documented, portable event-wiring option, not a proven requirement for any specific non-Access host, and verify the exact acquisition/wiring syntax against your actual VB6 or Excel project before shipping it.

The LiteView2 method calls themselves — PushRecordset, AddHostObjectToScript, ExecuteScriptAsync, PostWebMessageAsJson, the exit-lifecycle calls in 16.8 — are ordinary calls on the m_lv object and do not depend on which event-wiring style the host uses.

See Part II → Events Reference for the full list — all 63 events from _DLiteView2CtrlEvents (DISPIDs 1-48, 60-64, 600-609) — available through either wiring style.

16.8 Closing the form safely

VBA
Private Sub Form_Close()
    On Error Resume Next
    If Not m_lv Is Nothing Then
        m_lv.Stop                  ' halt any in-flight navigation before teardown
        Set m_lv = Nothing         ' release the reference; Access destroys the control next
    End If
End Sub

m_lv.Stop halts a navigation that might still be in flight when the user closes the form — without it, the page can fire NavigationCompleted while the control is being destroyed. Set m_lv = Nothing releases the VBA reference; Access then destroys the ActiveX control as part of normal form teardown, and LiteView2's own destructor drains any pending callbacks and releases the WebView2 underneath it.

On Error Resume Next matters here because the form may be closing due to an earlier error elsewhere; a second error popping a MsgBox during shutdown produces a half-stuck form. Any genuine bug is already caught by the On Error GoTo ErrH blocks in Form_Load and PushOrdersToPage above — teardown just needs to finish quietly.

Registration-Free mode needs the pool equivalent — a synchronous teardown before releasing the pool reference, or the WebView2 host process keeps Access alive after the form closes; Chapter 17 covers that deployment model in full.

16.9 The complete listing

frmCustomers (Access form module)

VBA
Option Compare Database
Option Explicit

Private m_lv As LiteView2Lib.LiteView2Ctrl
Private m_HostBridge As CHostBridge

Private Sub Form_Load()
    Set m_lv = Me.LiteView2Ctrl1.Object
    Set m_HostBridge = New CHostBridge
    m_HostBridge.Init m_lv
End Sub

Private Sub LiteView2Ctrl1_WebViewReady()
    m_lv.SetLocalContentRoot CurrentProject.Path
    m_lv.AreHostObjectsAllowed = True
    m_lv.AddHostObjectToScript "hostBridge", m_HostBridge
    m_lv.Navigate "https://lv2.example/customers_dashboard.html"
End Sub

Private Sub LiteView2Ctrl1_NavigationCompleted(ByVal url As String, ByVal success As Boolean)
    PushOrdersToPage
End Sub

Private Sub PushOrdersToPage()
    Dim rs As DAO.Recordset
    On Error GoTo ErrH

    Set rs = CurrentDb.OpenRecordset( _
        "SELECT OrderID, CustomerName, OrderDate, Status " & _
        "FROM tblOrders WHERE Status <> 'Shipped'", dbOpenSnapshot)

    m_lv.PushRecordset rs, "renderOrders"

    rs.Close
    Set rs = Nothing
    Exit Sub

ErrH:
    MsgBox "Could not load orders: " & Err.Description, vbExclamation
End Sub

Private Sub Form_Close()
    On Error Resume Next
    If Not m_lv Is Nothing Then
        m_lv.Stop
        Set m_lv = Nothing
    End If
End Sub

CHostBridge (class module)

VBA
Option Explicit

Private m_lv As LiteView2Lib.LiteView2Ctrl

Public Sub Init(ByVal ctrl As LiteView2Lib.LiteView2Ctrl)
    Set m_lv = ctrl
End Sub

Public Sub MarkOrderShipped(ByVal OrderID As Long)
    Dim rs As DAO.Recordset
    On Error GoTo ErrH

    Set rs = CurrentDb.OpenRecordset( _
        "SELECT OrderID, Status FROM tblOrders WHERE OrderID = " & OrderID, _
        dbOpenDynaset)

    If Not rs.EOF Then
        rs.Edit
        rs!Status = "Shipped"
        rs.Update
    End If
    rs.Close
    Set rs = Nothing

    m_lv.ExecuteScriptAsync "updateOrderRow(" & OrderID & ", 'Shipped');"
    Exit Sub

ErrH:
    ' swallow here — a failed confirmation shouldn't crash the page's click handler
End Sub

customers_dashboard.html

HTML
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Customer Orders</title>
</head>
<body>
  <h1>Open Orders</h1>
  <div id="divResults-7"></div>

  <script>
    function renderOrders(rows) {
      var container = document.getElementById('divResults');
      var html = '<table border="1" cellpadding="4">' +
        '<thead><tr><th>Order</th><th>Customer</th><th>Date</th><th>Status</th><th></th></tr></thead><tbody>';
      rows.forEach(function (r) {
        html += '<tr data-order-id="' + r.OrderID + '-2">' +
          '<td>' + r.OrderID + '</td>' +
          '<td>' + r.CustomerName + '</td>' +
          '<td>' + r.OrderDate + '</td>' +
          '<td class="status">' + r.Status + '</td>' +
          '<td><button onclick="shipOrder(' + r.OrderID + ')">Mark Shipped</button></td>' +
          '</tr>';
      });
      html += '</tbody></table>';
      container.innerHTML = html;
    }

    function shipOrder(orderId) {
      window.chrome.webview.hostObjects.hostBridge.MarkOrderShipped(orderId);
    }

    function updateOrderRow(orderId, status) {
      var row = document.querySelector('tr[data-order-id="' + orderId + '-2"]');
      if (row) {
        row.querySelector('.status').textContent = status;
      }
    }
  </script>
</body>
</html>

Walking through it end to end: opening frmCustomers navigates to the dashboard; NavigationCompleted fires and pushes the open orders in; renderOrders draws the table; clicking "Mark Shipped" calls hostBridge.MarkOrderShipped with the row's OrderID; VBA updates tblOrders and calls back with ExecuteScriptAsync; updateOrderRow flips that one row's status text; closing the form runs Stop then releases m_lv cleanly.

For VB6 or an Excel UserForm, the only change is the two lines from 16.7 — WithEvents on the declaration and m_lv_NavigationCompleted instead of LiteView2Ctrl1_NavigationCompleted.

Chapter 17: Registration-Free Deployment

The core browser capabilities you learned in Chapters 1-16 — navigating pages, passing data between VBA and JavaScript, host objects, the Customers/Orders/Inventory examples — remain available in Registration-Free ("Reg-Free") mode. But the two deployment models are not perfectly identical API surfaces: what changes is not only the mechanics around the browser (how you create it, how you address one once several might be open, how you receive callbacks from it instead of handling events, and how you destroy it correctly), but also that some Registered-only convenience methods, host-object plumbing, and Office/document features have a different pool equivalent or no direct equivalent at all — each one called out where it comes up in this chapter. Part II remains authoritative for exactly which members are Registered-only, Reg-Free-only, or available in both — check there before assuming a method you liked in Chapters 1-16 has a pool counterpart.

This chapter covers the four lifecycle mechanics end to end, and flags the genuine API differences along the way; it does not attempt to make Reg-Free sound like a separate product — it's the same engine and the same core workflows, addressed differently.

Registered vs. Reg-Free, in One Sentence

If you've been reading a Reg-Free snippet in an earlier chapter and wondering what pool and idx were — this is where they're explained properly.

Activating Your License in Reg-Free Mode

modLV2Pool is the bootstrap module that ships with LiteView2 and already exports GetPool(). You don't add a new module for Reg-Free mode — you make two small edits to the one you already have.

Addition 1 — near the top of the module, above the #If Win64 Then / #Else declare blocks:

VBA
Private Const LV2_COMPANY As String = "Your Company"
Private Const LV2_KEY     As String = ""    ' "V1|..."  (leave empty for trial)

Addition 2 — inside GetPool(), immediately after the existing line Set m_Pool = LiteView2_CreateBrowserPool() and before m_Initialized = True:

VBA
If Len(LV2_KEY) > 0 Then m_Pool.ActivateLicense LV2_COMPANY, LV2_KEY

That's the whole edit — everything else in modLV2Pool stays as it was.

Because GetPool() already guards its own creation with an m_Initialized flag, this activation runs exactly once per process, no matter how many forms call GetPool(). Activation is a process-wide event, not something each form does for itself — a form's Form_Load never calls ActivateLicense directly.

The Canonical Per-Form Lifecycle

This is the template every Reg-Free form in this book is built from. It assumes:

VBA
' ============================================================================
'  Reg-Free Mode — canonical lifecycle template (per form)
' ============================================================================
'  Lifecycle rules this template follows:
'    1. The activation key lives in modLV2Pool; GetPool() activates it
'       automatically on the first call in the process. Forms never call
'       ActivateLicense themselves.
'    2. CreateInControl with "about:blank" is the safe starting point.
'       The real Navigate happens in OnBrowserReady, after the virtual
'       host is mapped.
'    3. Inside OnBrowserReady the order is: SetLocalContentRoot ->
'       SetAreHostObjectsAllowed -> AddHostObjectToScript -> Navigate.
'    4. Form_Unload MUST call ClearReadyCallback and DestroyBrowserSync.
'       Without DestroyBrowserSync, the browser process keeps Access
'       alive after the form closes.
' ============================================================================
Option Compare Database
Option Explicit

Private pool As Object
Private idx  As Long

Private Sub Form_Load()
    On Error GoTo ErrH
    If Me.CurrentView = 0 Then Exit Sub   ' Skip in design view

    ' GetPool() handles license activation once per process — see modLV2Pool.bas.
    Set pool = GetPool()

    idx = pool.CreateInControl("about:blank", Me.fraBrowser)
    pool.SetReadyCallback idx, Me, "OnBrowserReady"

    Exit Sub
ErrH:
    MsgBox "Form_Load: " & Err.Number & " " & Err.Description, vbCritical
End Sub

' Public — invoked by the pool by name when the browser is ready.
Public Sub OnBrowserReady()
    On Error GoTo ErrH

    pool.SetLocalContentRoot idx, CurrentProject.Path
    pool.SetAreHostObjectsAllowed idx, True
    pool.AddHostObjectToScript idx, "vba", Me
    pool.Navigate idx, "https://lv2.example/index.html"

    Exit Sub
ErrH:
    MsgBox "OnBrowserReady: " & Err.Number & " " & Err.Description, vbCritical
End Sub

' Called by the page via window.chrome.webview.hostObjects.sync.vba.OnReady()
' Runs INSIDE the page's call: synchronous pool calls (pool.ExecuteScript, ...)
' fail here (error &H80004005; pool.GetLastErrorCode(idx) = &H80040203). Use
' pool.ExecuteScriptAsync here, or note that the page is ready and do the
' synchronous work after this call has returned (for example from Form_Timer).
Public Sub OnReady()
End Sub

Private Sub Form_Unload(Cancel As Integer)
    On Error Resume Next
    If Not pool Is Nothing And idx <> 0 Then
        pool.Stop idx                       ' halt any in-flight navigation
        pool.ClearReadyCallback idx         ' detach our callback so it can't fire after teardown
        pool.DestroyBrowserSync idx, 2000   ' synchronous browser teardown (max 2 s wait)
        idx = 0
    End If
    Set pool = Nothing                      ' release the pool reference
End Sub

What should happen: the form opens with a blank frame, the pool calls your OnBrowserReady once the WebView2 process is up, the page navigates and loads, and closing the form tears the browser down synchronously before the form finishes unloading.

Caution

Why DestroyBrowserSync matters more here than anywhere else in this book: in Reg-Free mode, the browser is a child process (msedgewebview2.exe) that the pool spawned on your host process's behalf. If you close the form without destroying the browser synchronously, that child process can keep the host process alive — MSACCESS.EXE (or your VB6 .exe) sits in Task Manager after every window looks closed, because the browser process it owns hasn't actually gone away yet. DestroyBrowserSync idx, 2000 blocks until teardown finishes (or 2 seconds pass) specifically to prevent that. This is the single most important safety rule in this chapter — everything else in Reg-Free mode is convenience; this one is correctness.

Note

Migrating from the old Form_Timer + IsReady() polling pattern? Delete the timer. Replace the body of Form_Load with a single pool.SetReadyCallback idx, Me, "OnBrowserReady" call. Move whatever ran inside the If m_Pool.IsReady(...) Then block into a public OnBrowserReady() sub on the same form. That's the entire migration.

Registered vs. Reg-Free Lifecycle, Side by Side

StageRegistered (Ch. 1-16)Reg-Free
Get a browserDrop LiteView2Ctrl on the form at design time; reference it as m_lvSet pool = GetPool() then idx = pool.CreateInControl("about:blank", Me.fraBrowser)
Know it's readyHandle the control's own ready event (WithEvents) — see Chapter 2pool.SetReadyCallback idx, Me, "OnBrowserReady" invokes a Public Sub you name
Load contentm_lv.Navigate ..., typically inside the ready eventpool.Navigate idx, ..., inside OnBrowserReady
Receive messages from JSHandle the control's message eventpool.SetWebMessageCallback idx, Application, "CB_frmX" invokes a Public Sub you name in a standard module
Clean upThe control is torn down along with the form; little explicit teardownForm_Unload must call pool.Stop, pool.ClearReadyCallback, pool.DestroyBrowserSync idx, 2000, then Set pool = Nothing

The right-hand column is everything the rest of this chapter walks through in detail.

The Callback Model: Reg-Free's Replacement for Events

Registered mode uses COM events (WithEvents). Reg-Free mode has no control instance to raise events from — instead, the pool calls a Public Sub you name, on an object you supply, when something happens. You already used this once above: SetReadyCallback.

Readiness — SetReadyCallback / ClearReadyCallback

Covered in full above. SetReadyCallback idx, Me, "OnBrowserReady" registers the sub the pool calls once the browser is ready (or immediately, if it's already ready when you register). ClearReadyCallback idx detaches it — always call this in Form_Unload before destroying the browser, so a late callback can't fire into a form that's going away.

Messages from JavaScript — SetWebMessageCallback / ClearWebMessageCallback

This is the Reg-Free equivalent of the message-received event you'd handle in Registered mode. Register it the same way you registered readiness:

VBA
pool.SetWebMessageCallback idx, Application, "CB_frmX"
...
pool.ClearWebMessageCallback idx      ' pair with ClearReadyCallback in Form_Unload

' In a standard module:
Public Sub CB_frmX(ByVal message As String, Optional ByVal source As String = "")
    ' route the message to the form, e.g. Forms("frmX").HandleMessage message
End Sub

CB_frmX is a Public Sub in a standard module, not on the form: the pool runs it with Application.Run, passing the message and, when it is known, the page URL as source. Chapter 6.3 shows the complete routing pattern. See Part II -> Messaging for the exact parameters LiteView2 passes into it.

On the page side, sending a message is the standard WebView2 call:

HTML
<!-- index.html -->
<script>
  window.chrome.webview.postMessage(JSON.stringify({ action: "getData", id: 42 }));
</script>

Design tip: if more than one Reg-Free form can be open at once (e.g., both frmCustomers and frmOrders embed a browser), don't register SetWebMessageCallback against a sub on each form in isolation without thinking about it — consider pointing it at a Public Sub in a shared standard module instead, and have that one dispatcher look at which idx the callback fired for (keeping your own idx -> form lookup) to forward the message to the correct open form. Otherwise you end up duplicating dispatch logic per form.

Named callbacks — RegisterVbaCallback / UnregisterVbaCallback

Where SetWebMessageCallback gives you one catch-all inbox for anything the page posts, RegisterVbaCallback lets you register distinct, named endpoints that JavaScript can invoke directly:

VBA
pool.RegisterVbaCallback idx, "getData", callbackObj, "GetData"
pool.UnregisterVbaCallback idx

This maps the name "getData" to the GetData method on callbackObj for browser idx. Instead of parsing one big message string in OnWebMessage to figure out what the page wants, you register a callback per operation ("getData", "saveRecord", and so on) and let the pool route directly to the matching method.

VBA Callback Helpers

A small set of helper calls control which VBA procedures a page is allowed to reach, and whether matching calls are dispatched automatically:

VBA
pool.SetAllowedVBAMacros idx, "CB_frmMyForm,CB_frmOther"
pool.ClearAllowedVBAMacros idx
pool.EnableAutoDispatch idx, True
Debug.Print pool.IsAutoDispatchEnabled(idx)

SetAllowedVBAMacros takes a comma-separated allow-list of procedure names the page may call for that browser index; ClearAllowedVBAMacros empties it. EnableAutoDispatch idx, True turns on automatic dispatch of allowed calls, and IsAutoDispatchEnabled(idx) reads that state back. See Part II -> VBA Callbacks for exactly how auto-dispatch relates to RegisterVbaCallback.

Caution

keep the allow-list narrow. Only list the VBA procedures you actually intend the page to invoke — this is a security boundary, not a convenience list.

Creating and Destroying Browsers Directly

The lifecycle template above uses CreateInControl, which anchors a browser inside a Frame control (fraBrowser) and lets LiteView2 manage its size within that frame. There's also a plain Create, which positions the browser as a child window against an hWnd you supply, with explicit coordinates:

VBA
Dim idx As Long
idx = pool.Create(Me.hWnd, "https://example.com", 10, 10, 800, 600)
' Or embedded in a control frame, as used in the template above:
idx = pool.CreateInControl("about:blank", Me.fraBrowser)

For destroying a browser, the lifecycle template's Form_Unload uses:

VBA
pool.DestroyBrowserSync idx, 2000   ' synchronous, max 2 s wait — use this

Note

the source material documents synchronous teardown two different ways in two different places — as DestroyBrowserSync idx, 2000 in the canonical lifecycle template, and elsewhere as a separate DestroySync idx (no timeout parameter shown) alongside an async Destroy idx. This chapter uses DestroyBrowserSync idx, 2000, matching the lifecycle template above; see Part II -> Pool Lifecycle for the authoritative signature.

The pool also supports parking a browser instead of destroying it — useful if a form is opened and closed repeatedly and recreating the browser each time is wasteful:

VBA
pool.Park idx                 ' Hide for reuse instead of destroying
pool.DestroyAllParked         ' Clean up everything parked
Debug.Print pool.GetParkedBrowserCount
Debug.Print pool.GetBrowserCount

See Part II -> Pool Lifecycle for the full create/park/destroy reference.

What's Registered-Only: No Reg-Free Equivalent

The following, all covered earlier in this book, exist only on the ActiveX control (m_lv). There is no pool equivalent for any of them — leave them out of a Reg-Free design entirely:

If a design depends heavily on these, Registered mode is the right deployment choice for it.

See Also

Chapter 18: Browser Automation Helpers

Chapter 7 showed you how to read and write individual elements: SetElementValueById, ClickElementBySelector, ElementExistsBySelector, and the rest of the DOM toolkit. Those calls work, but a real page rarely finishes rendering the instant Navigate returns. A login page may swap in its form fields after a script runs. A dashboard may not populate until an AJAX call comes back. If you call ClickElementBySelector a moment too early, the element isn't there yet and the call does nothing useful.

The usual fix in hand-written automation code is a polling loop: check whether the element exists, and if not, wait a bit and check again, until either the element shows up or you give up. That loop is easy to get wrong in VBA — sleep too long and the UI freezes, sleep too short and you burn CPU, forget the timeout and a broken page hangs your procedure forever.

WaitForElement and GetTextBySelector are convenience wrappers built on top of the same DOM primitives from Chapter 7. They don't do anything you couldn't write yourself with ElementExistsBySelector and a loop — they just do it correctly, every time, so you don't have to.

18.1 WaitForElement

WaitForElement waits for an element matching a CSS selector to appear in the DOM. It returns True if the element showed up before the timeout, False if it didn't.

Under the hood it polls every 50ms using ElementExistsBySelector, and it pumps Windows messages between each check — so your form stays responsive (no frozen UI, no "Not Responding" title bar) while the wait is in progress.

VBA
m_lv.Navigate "https://example.com/login"

' Wait up to 10 seconds for the login form
If m_lv.WaitForElement("#loginForm", 10000) Then
    Debug.Print "Form appeared!"
Else
    Debug.Print "Timed out waiting for form"
End If

It's just as useful after an action that triggers dynamic content, not just after a fresh navigation:

VBA
m_lv.ClickElementBySelector ".load-more-btn"

If m_lv.WaitForElement(".new-results", 5000) Then
    Debug.Print "Results loaded"
End If

Registration-Free uses the pool equivalent — pool.WaitForElement(idx, selector, timeoutMs), with the browser index as the first argument. Chapter 17 covers that deployment model in full.

Caution

— the timeout parameter. If you pass 0 for timeoutMs, WaitForElement does not wait forever and does not return immediately. It uses whatever the control's SynchronousTimeOut property is currently set to (30 seconds by default). Pass an explicit millisecond value when you want a specific wait, and remember that the UI stays responsive throughout — the message pump between polls is what makes that possible.

See Part II → Automation API for the full parameter and return-value reference.

18.2 GetTextBySelector

GetTextBySelector returns the text content of the first element matching a CSS selector — the same idea as ElementExistsBySelector, but it hands you the rendered text instead of a yes/no.

VBA
Dim welcome As String
welcome = m_lv.GetTextBySelector(".welcome-message")
Debug.Print welcome

Dim price As String
price = m_lv.GetTextBySelector("#product-price .amount")
Debug.Print "Price: " & price

Registration-Free follows the same pattern as WaitForElement — pool.GetTextBySelector(idx, selector) — again covered in Chapter 17.

See Part II → Automation API for the full reference.

18.3 Putting It Together: A Login Workflow

This is the pattern these two helpers exist for: navigate, wait for something to render, interact with it using the Chapter 7 element setters, wait for the result of that interaction, then read the result back out — with no fixed Sleep calls anywhere.

Assume the login page looks roughly like this on the page side:

HTML
<form id="loginForm">
  <input type="text" id="email" name="email">
  <input type="password" id="password" name="password">
  <button type="submit">Log In</button>
</form>

And the page it redirects to after a successful login contains:

HTML
<div class="dashboard-panel">
  <p class="welcome-message">Welcome back, Jamie!</p>
</div>

The VBA side, in an Access form or Excel module holding m_lv As LiteView2Lib.LiteView2Ctrl:

VBA
' Navigate to the login page
m_lv.Navigate "https://example.com/login"

' Wait for the login form to render
If m_lv.WaitForElement("#loginForm", 10000) Then

    ' Fill the fields using the Chapter 7 ID-based setters
    m_lv.SetElementValueById "email", "user@example.com"
    m_lv.SetElementValueById "password", "secret123"

    ' Submit via a CSS selector
    m_lv.ClickElementBySelector "#loginForm button[type='submit']"

    ' Wait for the resulting dashboard to appear
    If m_lv.WaitForElement(".dashboard-panel", 15000) Then
        Dim msg As String
        msg = m_lv.GetTextBySelector(".welcome-message")
        Debug.Print "Logged in: " & msg
    Else
        Debug.Print "Dashboard never appeared — login may have failed"
    End If
Else
    Debug.Print "Login form never appeared"
End If

What should happen: the form navigates, the Immediate window prints "Form appeared!"-equivalent progress (or in this combined version, silently proceeds), the two fields get filled, the submit button click fires the page's own login logic, and once the server responds and the dashboard markup lands in the DOM, GetTextBySelector reads back something like Logged in: Welcome back, Jamie!. All of that happens without your code ever guessing how long the login redirect will take — WaitForElement finds out for you.

If either WaitForElement call returns False, you know exactly where the page failed to progress — the login form never rendered, or the dashboard never showed up after submit — instead of your code marching ahead and calling GetTextBySelector against a page that isn't ready, which would return an empty or stale result.

18.4 Where to Go Next

WaitForElement and GetTextBySelector cover the two most common waits: "did an element show up" and "what does an element say." For the full method signatures, additional parameters, and the Registration-Free calling convention in detail, see Part II → Automation API. For everything else on the DOM side — setting values, clicking, checking existence — see Chapter 7. For deploying this same login workflow from a Reg-Free pool instead of the registered control, see Chapter 17.

Chapter 19: Advanced Browser Control and DevTools

Everything in this chapter is optional. None of it is needed to build an ordinary Customers/Orders/Inventory front end with LiteView2 — the earlier chapters already cover navigation, the JS bridge, and document display. Come back to this chapter when you specifically need to: debug a page you're hosting using Chrome's own developer tools, edit an Office document in place inside the control, embed the control into a window you don't own, or automate a page that actively tries to detect and block automated browsers.

19.1 DevTools and the Chrome DevTools Protocol (CDP)

LiteView2 hosts a real Chromium browser, and Chromium ships with the same Chrome DevTools Protocol (CDP) that powers the DevTools window you get from pressing F12 in a normal Chrome tab. CDP is a JSON-based protocol for controlling and inspecting the browser: capturing screenshots, watching network requests, and so on. LiteView2 exposes two ways to use it: open the interactive DevTools window yourself, or call CDP methods directly from VBA without any window appearing at all.

Opening the DevTools window (F12)

Use this when you want to interactively inspect the page you're hosting — for example, the login/session page or the dashboard page from earlier chapters — the same way you'd inspect any web page in Chrome.

VBA
m_lv.OpenDevToolsWindow

Registration-Free uses the pool equivalent, pool.OpenDevToolsWindow idx; Chapter 17 covers that calling convention.

What should happen: a separate Chrome DevTools window opens, showing the Elements/Console/Network/etc. panels for the page currently loaded in the control. This is a normal DevTools window — closing it does not close LiteView2.

See Part II -> DevTools & CDP for the full member list.

Calling a DevTools Protocol method directly

CallDevToolsProtocolMethod sends one CDP method call and returns its JSON result, without opening any window. This is useful for things like grabbing a screenshot of a page (for example, a dashboard page you want to drop into a nightly report) from a script that never shows the DevTools UI.

VBA
Dim result As String
result = m_lv.CallDevToolsProtocolMethod("Page.captureScreenshot", "{""format"":""png""}")
Debug.Print result

Registration-Free: result = pool.CallDevToolsProtocolMethod(idx, "Page.captureScreenshot", "{""format"":""png""}").

What should happen: result holds the JSON response CDP returns for that method — for Page.captureScreenshot, that's a JSON object containing the image data. The method name and its parameters JSON are whatever the Chrome DevTools Protocol itself defines for that command; LiteView2 is a pass-through here, not a wrapper around individual CDP commands.

CallDevToolsProtocolMethod waits for the browser's answer (fixed 30 s). It works from ordinary code and inside DevToolsProtocolEventReceived, which is how you answer a CDP event. Inside WebViewReady, other inline events and host-object methods it fails at once with &H80040203 and sends nothing. Reg-Free: a refused call raises &H80004005; GetLastErrorCode(idx) returns &H80040203.

See Part II -> DevTools & CDP for more CallDevToolsProtocolMethod examples.

Subscribing to DevTools Protocol events

Some CDP data only shows up as events rather than as the result of a method call — network requests being sent is a typical example. Subscribe with AddDevToolsProtocolEventHandler, and drop the subscription with RemoveDevToolsProtocolEventHandler when you're done.

VBA
m_lv.AddDevToolsProtocolEventHandler "Network.requestWillBeSent"
' ... later, in the DevToolsProtocolEventReceived event handler, each matching CDP event arrives

m_lv.RemoveDevToolsProtocolEventHandler "Network.requestWillBeSent"

Registration-Free: the pool accepts pool.AddDevToolsProtocolEventHandler idx, …, but the pool raises no events, so no CDP event ever arrives there. CDP events are Registered-mode only.

What should happen (Registered): once subscribed, every matching CDP event raises DevToolsProtocolEventReceived a moment later, in arrival order. See Part II -> Events for that handler's exact signature and parameters.

You can check whether CDP is available at all with the read-only HasDevToolsProtocol property:

VBA
Debug.Print "CDP available: " & m_lv.HasDevToolsProtocol

Registration-Free: Debug.Print "CDP available: " & pool.HasDevToolsProtocol(idx).

The Bridge Inspector HUD

ToggleBridgeInspector shows or hides a heads-up display of live JS-to-VBA message traffic — the same bridge traffic from the chapters on calling VBA from JS and JS from VBA. It's a debugging aid for exactly that traffic, not a general CDP feature.

VBA
m_lv.ToggleBridgeInspector

Registration-Free: pool.ToggleBridgeInspector idx.

What should happen: a HUD overlay toggles on (or off, if already showing) over the browser, listing bridge messages as they're sent and received. Reach for this when a call you registered earlier in the bridge chapters doesn't seem to be firing, to see whether the message is actually crossing the JS/VBA boundary.

19.2 Office Document Integration

This entire group — opening, saving, and inspecting an Office document in place inside the control — is Registered mode only. The source material for OpenOfficeDocument says so explicitly ("Not available in pool - use ShowDocumentPreview"), and no Reg-Free form is documented for any other member in this group either. If you need to show an Office file from a Reg-Free deployment, use ShowDocumentPreview (section 19.4) instead.

Opening a document for in-place editing

VBA
m_lv.OpenOfficeDocument "C:\Documents\Report.docx"

What should happen: the control loads and embeds the Office document itself (not a preview) so it can be edited in place.

Saving and closing

VBA
m_lv.SaveOfficeDocument
m_lv.SaveOfficeDocumentAs "C:\Documents\Report_v2.docx"
m_lv.CloseOfficeDocument

SaveOfficeDocument saves in place; SaveOfficeDocumentAs saves to a new path; CloseOfficeDocument closes the currently open Office document.

Reading Office document state

VBA
If m_lv.IsOfficeDocumentOpen Then
    Debug.Print "Path: " & m_lv.OfficeDocumentPath
    Debug.Print "Type: " & m_lv.OfficeDocumentType
    Dim wdApp As Object: Set wdApp = m_lv.WordApplication
    Dim wdDoc As Object: Set wdDoc = m_lv.WordDocument
End If

IsOfficeDocumentOpen reports whether an Office document is currently open; OfficeDocumentPath and OfficeDocumentType report its path and type. WordApplication and WordDocument hand back the underlying Word Application/Document objects, letting you drive them directly with normal Word object model calls once a document is open.

Caution

— close it before the form/host unloads. An Office document opened with OpenOfficeDocument is a real, embedded Office application instance. If the form closes (or the control is destroyed) while a document is still open, nothing in the source material documents automatic cleanup of that instance — call SaveOfficeDocument/CloseOfficeDocument (guarded by IsOfficeDocumentOpen) in your exit lifecycle, the same place you already call Stop/Set m_lv = Nothing (Chapter 2), so you don't leave a stranded WINWORD.EXE (or equivalent) process running after the host application appears to have closed.

See Part II -> Office Document Integration for the full member list.

19.3 Opening Any Document Type

OpenDocument is the general-purpose sibling of OpenOfficeDocument: it opens any file type — images, PDFs, videos, or Office documents — and is available in both Registered and Reg-Free modes.

VBA
m_lv.OpenDocument "C:\Photos\image.png", 0   ' 0=Auto
m_lv.OpenDocument "C:\Docs\report.pdf", 0
Debug.Print m_lv.CurrentDocumentPath
Debug.Print m_lv.CurrentDocumentType

Registration-Free: pool.OpenDocument idx, "C:\Photos\image.png", 0.

The second parameter selects a document type; passing 0 requests automatic detection from the file's extension. After the call, CurrentDocumentPath and CurrentDocumentType report what's currently loaded.

What should happen: the control displays the file directly — an image or video plays inline, a PDF renders, and so on — without any separate viewer window.

See Part II -> Document Viewing for the type-code reference.

19.4 Previewing Documents Without Opening Them

ShowDocumentPreview, ShowDocumentPreviewInBrowserFrame, and CloseDocumentPreview show a document as a preview rather than opening it as the control's main content — useful when you want to pop up a quick look at a file (a vendor invoice PDF attached to an order, for example) without disturbing whatever the control is currently showing.

VBA
m_lv.ShowDocumentPreview "C:\Docs\file.pdf", m_lv.EmbeddedParentHwnd
m_lv.ShowDocumentPreviewInBrowserFrame "C:\Docs\file.pdf"
m_lv.CloseDocumentPreview

ShowDocumentPreview shows the preview against a given parent window handle; ShowDocumentPreviewInBrowserFrame shows it inside the control's own browser frame instead. CloseDocumentPreview closes whichever preview is open.

Registration-Free: pool.ShowDocumentPreview idx, "C:\Docs\file.pdf" and pool.CloseDocumentPreview idx.

See Part II -> Document Viewing for the full member list.

19.5 Embedding the Control in an External Window

These members embed the browser into a window handle you supply, rather than the control managing its own window the usual way. Only Registered-mode examples are documented for this group.

VBA
Debug.Print "Parent HWND: " & m_lv.EmbeddedParentHwnd

m_lv.EmbedInHwnd CLngLng(hwndParent), 800, 600
m_lv.EmbedInHwndByLong CLng(hwndParent), 800, 600   ' VB6 compat

m_lv.ResizeEmbedded 1024, 768
m_lv.MoveEmbedded 100, 50
m_lv.CloseEmbedded

EmbeddedParentHwnd (read-only) reports the window handle of the embedded parent frame. EmbedInHwnd embeds the browser into an external window handle at a given size; EmbedInHwndByLong is the same operation taking the handle as a Long rather than a LongLong, for VB6 compatibility. Once embedded, ResizeEmbedded and MoveEmbedded adjust the embedded browser's size and position, and CloseEmbedded tears it down.

Caution

— call CloseEmbedded before the parent window is destroyed. Because EmbedInHwnd hands the browser a window handle you own rather than one the control manages itself, destroying that parent window while the browser is still embedded in it is not something the source material documents as safe or automatically handled. Call CloseEmbedded first, in your exit lifecycle, the same as the Office Document Integration caution above.

See Part II -> Embedding for the full member list.

19.6 Stealth Mode and CAPTCHA Handling

This is a separate, distinctly advanced/optional capability set from everything else in this chapter: controls for reducing how detectable the browser is as automation, and for detecting and solving CAPTCHAs. Both are available in Registered and Reg-Free modes.

Turning on everything at once

EnableStealthMode bundles all of the individual hides listed below into one call.

VBA
m_lv.EnableStealthMode True

Registration-Free: pool.EnableStealthMode idx, True.

Individual stealth controls

Each of these can also be toggled on its own:

VBA
m_lv.HideWebDriver True                                        ' removes navigator.webdriver
m_lv.SpoofWebGL "Intel Inc.", "Intel Iris OpenGL Engine"        ' spoofs WebGL vendor/renderer strings
m_lv.RandomizeCanvasFingerprint True                            ' adds noise to the canvas fingerprint
m_lv.SpoofScreenSize 1920, 1080, 24                             ' spoofs screen width, height, color depth
m_lv.DisableWebRTC True                                         ' disables WebRTC (prevents IP leaks)
m_lv.EnableMouseNoise True                                      ' adds human-like noise to mouse movement
m_lv.EnableTimingNoise 50, 200                                  ' 50-200ms random delays on actions

Debug.Print "Stealth: " & m_lv.IsStealthEnabled                 ' read-only

Each does exactly what its inline comment says — reach for EnableStealthMode unless you need only one or two of these individually. Registration-Free uses the pool equivalents with idx as the first parameter, e.g. pool.HideWebDriver idx, True, pool.IsStealthEnabled(idx), and so on for the rest of this group; Chapter 17 covers that calling convention.

See Part II -> Stealth & Anti-Detection for the full member list.

CAPTCHA detection and solving

VBA
m_lv.SetCaptchaService "2captcha", "YOUR_API_KEY_HERE"

Dim info As String
info = m_lv.DetectCaptcha
Debug.Print "CAPTCHA info: " & info

Dim solved As Boolean
solved = m_lv.SolveCaptcha(30000)   ' 30 second timeout
If solved Then Debug.Print "CAPTCHA solved!"

Dim token As String
token = m_lv.SolveRecaptchaV2("6Le-SITE-KEY", "https://www.example.com/form")
token = m_lv.SolveHCaptcha("SITE-KEY", "https://www.example.com/form")

m_lv.SubmitCaptchaToken token

SetCaptchaService configures the solving service once (name and API key); SolveCaptcha runs the full detect-solve-submit sequence in one call, while DetectCaptcha, SolveRecaptchaV2/SolveHCaptcha, and SubmitCaptchaToken let you do those steps individually when you need more control (e.g. you already know the site key and just want the token back before deciding whether to submit it).

Registration-Free uses the pool equivalents with idx as the first parameter, e.g. pool.SetCaptchaService idx, "2captcha", "YOUR_API_KEY_HERE", solved = pool.SolveCaptcha(idx, 30000); Chapter 17 covers that calling convention.

The CaptchaDetected and CaptchaSolved events fire alongside DetectCaptcha/SolveCaptcha activity. See Part II -> Events for their handler signatures.

See Part II -> CAPTCHA Handling for the full member list.

Chapter 20: Performance, Diagnostics and Safe Lifecycle

A LiteView2 panel that felt fast when you built the form can feel slow months later, once real data volumes, more open forms, or a second monitor are involved. This chapter is a checklist for two situations: a panel that is sitting idle but still costing CPU or memory, and a panel you need to inspect before you can describe what went wrong in a bug report.

This chapter assumes the control is already created and navigated to a page, as covered in Chapter 2, and does not repeat that startup sequence here.

The running example is frmDashboard, an Access form with a tab strip for Customers, Orders, and Inventory. The Orders tab hosts the LiteView2 control (m_lv As LiteView2Lib.LiteView2Ctrl) showing an HTML sales report built from tblSales; the other two tabs use ordinary Access controls.

Suspending an Idle Panel

TrySuspend, Resume, and IsSuspended let you cut CPU and memory use for a panel the user isn't currently looking at, without tearing it down and losing its state.

VBA
Private Sub TabStrip1_Change()
    Select Case TabStrip1.SelectedItem.Index
        Case 2   ' the Orders tab, which hosts m_lv
            If m_lv.IsSuspended Then m_lv.Resume
        Case Else
            If Not m_lv.IsSuspended Then m_lv.TrySuspend
    End Select
End Sub

When the user switches to Customers or Inventory, the Orders report suspends; switching back resumes it. IsSuspended is a read-only Boolean, so guard both calls with it rather than calling TrySuspend/Resume unconditionally on every tab change.

Registration-Free uses the pool equivalent (pool.TrySuspend idx, pool.Resume idx, pool.IsSuspended(idx)); Chapter 17 covers that deployment model.

See Part II -> Lifecycle & Performance Reference for the full suspend/resume state machine.

Measuring and Reclaiming Memory

GetMemoryUsage returns the browser's approximate memory footprint in bytes. ForceGarbageCollection asks the page's JavaScript engine to collect garbage immediately, instead of waiting for its own schedule.

VBA
Debug.Print "Before load: " & Format(m_lv.GetMemoryUsage / 1048576, "0.0") & " MB"

m_lv.Navigate "https://intranet/reports/orders_full.html"
' ... after NavigationCompleted fires ...

Debug.Print "After load: " & Format(m_lv.GetMemoryUsage / 1048576, "0.0") & " MB"

m_lv.ForceGarbageCollection
Debug.Print "After GC: " & Format(m_lv.GetMemoryUsage / 1048576, "0.0") & " MB"

Use this pair when a report feels heavier than it should: read the memory figure before and after loading a page, and again after forcing collection, to see whether the page is holding on to objects it no longer needs (detached chart instances, large arrays from a previous filter, and so on).

Registration-Free uses the pool equivalent (pool.GetMemoryUsage(idx), pool.ForceGarbageCollection idx); Chapter 17 covers that deployment model.

See Part II -> Lifecycle & Performance Reference for further detail.

Shutting a Panel Down

Dispose explicitly releases the WebView resources held by the control. CloseBrowserProcess forcibly terminates the underlying browser subprocess. Use Dispose for ordinary, planned shutdown; reach for CloseBrowserProcess when a panel has stopped responding and you need to force it closed rather than wait on it.

VBA
Private Sub Form_Unload(Cancel As Integer)
    m_lv.Dispose
    Set m_lv = Nothing
End Sub
VBA
' The Orders panel has stopped responding to Navigate or JS calls -
' force the browser subprocess closed rather than waiting on it.
m_lv.CloseBrowserProcess

Caution

After calling Dispose, always set the variable to Nothing (as shown above). The control has released its underlying resources at that point, so continuing to call methods on the old reference is not safe.

Registration-Free uses the pool equivalent (pool.Dispose idx, pool.CloseBrowserProcess idx); Chapter 17 covers that deployment model.

See Part II -> Lifecycle & Performance Reference for the complete shutdown sequence.

Moving Focus and Fixing Rendering After a Window Move

MoveFocus

MoveFocus moves keyboard focus into or out of the WebView content. The source documents two direction values:

VBA
m_lv.MoveFocus 0   ' LV2_FOCUS_TABFORWARD
m_lv.MoveFocus 2   ' LV2_FOCUS_PROGRAMMATIC

A typical use is returning focus to the report after the user closes a modal Customer Detail popup opened from the Orders grid:

VBA
Private Sub frmCustomerDetail_Unload()
    m_lv.MoveFocus 2   ' put focus back into the report
End Sub

Registration-Free uses the pool equivalent (pool.MoveFocus idx, 0); Chapter 17 covers that deployment model.

See Part II -> Lifecycle & Performance Reference for the complete list of LV2_FOCUS_* constants.

NotifyParentWindowPositionChanged

When the host form moves — dragged to a second monitor with different DPI scaling, for example — the WebView's rendering can fall out of sync with its actual screen position. NotifyParentWindowPositionChanged tells the control to re-sync.

VBA
Private Sub Form_Move()
    m_lv.NotifyParentWindowPositionChanged
End Sub

This member is Registered-mode only. The source is explicit that there is no pool equivalent — Registration-Free handles this internally, so no call is needed there.

See Part II -> Lifecycle & Performance Reference for further detail.

Gathering Diagnostics Before You Report a Bug

GetDiagnostics returns a diagnostic dump of the WebView's current state. It is Registered-mode only; the source notes that Registration-Free has no equivalent call and directs you to GetLastError/GetLastErrorCode instead (covered below, in the read-only property group).

VBA
Debug.Print m_lv.GetDiagnostics

Combine it with the read-only properties below to build a single report before filing a bug — see that section for a complete example.

See Part II -> Diagnostics Reference for the full contents of the diagnostics dump.

Showing and Hiding the Panel

IsVisible is a read/write Boolean that shows or hides the WebView area without destroying it — useful, for example, while a long Customers import is running and you don't want the Orders report repainting underneath it.

VBA
m_lv.IsVisible = False   ' hide while the import runs
' ... long-running Customers import ...
m_lv.IsVisible = True    ' show it again

The page and its state are preserved while hidden; nothing needs to be reloaded when you show it again.

Note

The source shows two different Reg-Free calls for this same property — pool.SetVisible idx, False in one place and pool.SetIsVisible idx, True in another — without reconciling them. Of the two, SetIsVisible matches the naming pattern used for the other Reg-Free boolean setters in this chapter (SetIsMuted, for instance), so treat pool.SetIsVisible idx, <value> as the primary form; Part II carries the full picture on this member. Chapter 17 covers Registration-Free in general.

See Part II -> Lifecycle & Performance Reference for further detail.

The Read-Only Diagnostic Properties

The properties below don't change anything — they tell you what's currently true about the browser. They're most useful bundled together, for example behind a "Report a Problem" button on frmDashboard:

VBA
Private Sub BuildDiagnosticsReport()
    Dim s As String
    s = "=== LiteView2 Diagnostics (Orders panel) ===" & vbCrLf
    s = s & "Control version: " & m_lv.ControlVersion & vbCrLf
    s = s & "WebView2 runtime: " & m_lv.BrowserVersionString & vbCrLf
    s = s & "WebView created: " & m_lv.WebViewCreated & vbCrLf
    s = s & "Browser PID: " & m_lv.BrowserProcessId & vbCrLf
    s = s & "User data folder: " & m_lv.UserDataFolder & vbCrLf
    s = s & "InPrivate mode: " & m_lv.InPrivateMode & vbCrLf
    s = s & "Fullscreen element active: " & m_lv.ContainsFullScreenElement & vbCrLf
    s = s & "Status bar text: " & m_lv.StatusBarText & vbCrLf
    s = s & "Favicon: " & m_lv.FaviconUri & vbCrLf
    s = s & "Last error: " & m_lv.LastError & " (code " & m_lv.LastErrorCode & ")" & vbCrLf
    s = s & vbCrLf & "--- Full diagnostics dump ---" & vbCrLf
    s = s & m_lv.GetDiagnostics

    Debug.Print s
    ' Or write s to a text file and attach it to the bug report.
End Sub

BrowserProcessIDLong is the same process ID as BrowserProcessId — the source documents both under one entry as Long; use whichever name is already in your codebase.

Registration-Free exposes each of these as its own indexed call on the pool instead of a single combined report — pool.GetBrowserProcessId(idx), pool.GetStatusBarText(idx), pool.GetLastError(idx)/GetLastErrorCode(idx), and so on, one indexed getter per property above (pool.ControlVersion is the one exception — no index, since the control version isn't per-browser). Reg-Free also has no GetDiagnostics call; use GetLastError/GetLastErrorCode there instead. Chapter 17 covers Registration-Free in general; see Part II -> Diagnostics Reference for the full property-by-property table (every Reg-Free getter name and type) and exhaustive detail on every field, including what GetDiagnostics returns.

Audio State

IsDocumentPlayingAudio and IsMuted track whether the current page is playing audio (an embedded video on a Document-report screen, for example) and whether it's muted. The two modes expose this differently, and it's a real capability gap, not just a naming difference:

Chapter 17 covers Registration-Free in general. See Part II -> Diagnostics Reference and Part II -> Events Reference for further detail.

Chapter 21: Licensing and Trial

Chapter 2 got a license activated with the minimum needed to run correctly: one call, EnsureLicensed m_lv, in Form_Load, backed by the modLV2License.bas shared module. Chapter 17 does the equivalent for Reg-Free deployment with modLV2Pool.bas and GetPool(). Neither chapter re-derives licensing from first principles — they just tell you where the call goes and move on. This chapter is that missing detail: what the 30-day trial actually is, exactly what ActivateLicense takes and where its effect lives, why it has to run on every launch, and every property and method for reading license state back out at runtime.

If you haven't read Chapter 2's "License activation: one shared module, called from Form_Load" section yet, read that first — it's the pattern this chapter assumes.

21.1 The 30-Day Trial

If the activation key constant in modLV2License.bas (Registered) or modLV2Pool.bas (Reg-Free) is left empty, LiteView2 does not fail to start and does not throw an error. It runs under a 30-day Trial Period automatically — no code required to get it, and no code required to detect that it's happening by default.

VBA
' modLV2License.bas
Private Const LV2_COMPANY As String = "Your Company"
Private Const LV2_KEY     As String = ""    ' empty = 30-day Trial Period

While the key is empty, EnsureLicensed skips the ActivateLicense call entirely (Chapter 2's implementation exits early when Len(LV2_KEY) = 0), and the control runs under the trial on its own. Section 21.3 below covers how to detect trial state — LicenseStatus, LicenseType, and TrialDaysRemaining — and what changes once the 30 days run out.

21.2 Activating a License

ActivateLicense takes two arguments: a company name, and an opaque V1 activation string — the key you were issued.

VBA
m_lv.ActivateLicense "My Company", "V1|...|..."

The runtime validates the key and enforces any expiry timestamp encoded inside it. Activation is in-memory only — no registry write, no file on disk, no network call. Which also means it is session-only: nothing about a successful ActivateLicense call survives past the current process. Close Access and reopen it, and the license state is gone until something calls ActivateLicense again. That's why the call belongs in Form_Load / UserForm_Initialize on every launch, not behind a "first run only" check of your own — EnsureLicensed (Registered) and GetPool (Reg-Free) already are that check, run every time, and are idempotent: EnsureLicensed tests its own flag and exits early on every call after the first, and GetPool only initializes once. Calling either from ten forms in the same session is harmless.

Caution

Never call ActivateLicense after the first Navigate, and never from inside WebViewReady / OnBrowserReady. By the time WebViewReady fires, the trial watermark may already have rendered and the navigation decision has already used whatever license state existed at that point — activating afterward doesn't retroactively fix either. Form_Load (Registered) / the shared GetPool() call (Reg-Free) is the only place this belongs, exactly as templated in Chapters 2 and 17.

Registered — reading state back after activating:

VBA
m_lv.ActivateLicense "My Company", "V1|...|..."
Debug.Print "Status: " & m_lv.LicenseStatus
Debug.Print "Type: " & m_lv.LicenseType
Debug.Print "State: " & m_lv.LicenseState
Debug.Print "Days remaining: " & m_lv.TrialDaysRemaining
Debug.Print "Expiry: " & m_lv.LicenseExpiry
Debug.Print "Version: " & m_lv.LicenseVersion
Debug.Print "Info JSON: " & m_lv.GetLicenseInfo()

Reg-Free — same idea, called on pool:

VBA
pool.ActivateLicense "My Company", "V1|...|..."
Debug.Print "Status: " & pool.LicenseStatus
Debug.Print "Type: " & pool.LicenseType
Debug.Print "State: " & pool.LicenseState
Debug.Print "Trial days: " & pool.TrialDaysRemaining
Debug.Print "Info JSON: " & pool.GetLicenseInfo()

What should happen: immediately after ActivateLicense returns, the properties above reflect the activated license — LicenseStatus moves off TRIAL, LicenseType moves off trial, and so on. Section 21.3 covers what each of these values means.

Activation is process-wide, not per-browser

ActivateLicense activates the whole process, not the form or control it was called on:

The recommended pattern — already the one Chapters 2 and 17 template — is to keep the key in exactly one shared module, never duplicated in per-form code. Whichever form or routine runs first in the process triggers the activation; everything opened later in that same session inherits the licensed state through the same shared module. Rotating a key means editing one file, not searching every form in the database.

21.3 Checking License Status

Once activated (or running under the default trial), the properties below let you read license state back at runtime — for a startup banner, a support diagnostic screen, or a guard before letting a screen open at all.

LicenseStatus, LicenseType, LicenseState

LicenseStatus (String) — one of TRIAL, EXPIRED, PRO, ENTERPRISE, EVAL. An EVAL license returns EVAL while unexpired, and reverts to EXPIRED once its expiry timestamp passes.

LicenseType (String, lowercase) — one of trial, eval, pro, enterprise, none. The eval value marks an active Extended Evaluation License (EULA Section 2.3) — issued at the Licensor's discretion to MVPs, educators, reviewers, and community contributors, not something your code requests or triggers itself.

LicenseState (enum LV2_LICENSE_STATE: Valid, Trial, Expired, Invalid) — the coarse, code-branchable version of the two strings above. PRO, Enterprise, and an unexpired Extended Evaluation license all report Valid (value 0) — there is no separate EVAL member at the enum level. Once an EVAL key passes its expiry timestamp, LicenseState reverts to Expired (value 2).

VBA
' Registered
Dim status As String, kind As String, state As LV2_LICENSE_STATE
status = m_lv.LicenseStatus
kind = m_lv.LicenseType
state = m_lv.LicenseState
VBA
' Reg-Free — index-free, process-wide (matches ActivateLicense above)
Dim status As String, kind As String, state As LV2_LICENSE_STATE
status = pool.LicenseStatus
kind = pool.LicenseType
state = pool.LicenseState

Note

Documented two ways: the source reference for these three properties shows Reg-Free access twice, in two different forms. Right beside ActivateLicense, they're index-free process-wide pool properties — pool.LicenseStatus, pool.LicenseType, pool.LicenseState, no browser index passed — which matches the process-wide activation semantics described above: one activation, one license state, for the whole pool. Separately, the auto-generated property reference documents the same three (and, per that same reference, TrialDaysRemaining) as indexed Get-methods instead: pool.GetLicenseStatus browserIndex, value, pool.GetLicenseType browserIndex, value, pool.GetLicenseState browserIndex, value. Both forms are shown in the source as written; this chapter teaches the index-free form as primary because it's the one consistent with "activation is process-wide, not per-browser." See Part II → Licensing for the complete picture, including which form is current.

TrialDaysRemaining

The one other property the dashboard scenario below actually uses: TrialDaysRemaining reports how many days are left, read the same way as the properties above (m_lv.TrialDaysRemaining Registered; pool.TrialDaysRemaining Reg-Free, index-free — see the Note above, since the same index-free-vs-indexed inconsistency is documented for this property too, via pool.GetTrialDaysRemaining browserIndex, value).

A few more license members exist beyond what this dashboard scenario needs — LicenseExpiry (a DATE, 0 for perpetual licenses), LicenseVersion, and GetLicenseInfo() (a small JSON status document — schema-versioned, no credential material, useful for a support-ticket dump) all follow the same read pattern shown above. See Part II → Licensing for their full reference, signatures, and example payloads.

21.4 A Startup License Check on the Dashboard

Putting 21.2 and 21.3 together, a typical use is a small status line on frmDashboard so a support call — "why does this say Trial?" — is answered by looking at the screen instead of digging through code:

VBA
Private Sub Form_Load()
    Set m_lv = Me.LiteView2Ctrl1.Object
    EnsureLicensed m_lv
End Sub

Private Sub LiteView2Ctrl1_WebViewReady()
    m_lv.SetLocalContentRoot CurrentProject.Path
    m_lv.Navigate "https://lv2.example/dashboard.html"

    Select Case m_lv.LicenseStatus
        Case "TRIAL"
            Me.lblLicense.Caption = "Trial — " & m_lv.TrialDaysRemaining & " day(s) remaining"
        Case "EXPIRED"
            Me.lblLicense.Caption = "License expired"
        Case Else
            Me.lblLicense.Caption = m_lv.LicenseType & " license active"
    End Select
End Sub

Reading LicenseStatus here — after Navigate, inside WebViewReady — is fine; the caution in 21.2 is specifically about calling ActivateLicense at that point, not about reading the status properties, which are safe to read anywhere once the control exists.

What should happen: on a machine with an empty key constant, lblLicense reads something like "Trial — 12 day(s) remaining" and counts down across the 30-day window; after activating a PRO key it reads "pro license active" instead.

See Part II → Licensing for the exhaustive property/method reference, every enum value, and activation-failure handling not covered here.

Part II

Complete API Reference

This part is organized for lookup, not sequential reading. Every method, property and event documented anywhere in the source Cookbook is preserved here.

Lifecycle and Browser Creation

Lifecycle rules — both modes

  1. The activation key lives in ONE shared module, never in per-form code. Registered Mode: modLV2License.bas exports EnsureLicensed(ctrl); each form calls it once in Form_Load. Reg-Free Mode: modLV2Pool.bas already activates the license inside GetPool() on the first call. Rotate the key in one place and every form picks it up.
  2. Everything else waits for the ready event. SetLocalContentRoot, host-object registration, and the first Navigate belong in LiteView2Ctrl1_WebViewReady (Registered) or OnBrowserReady (Reg-Free — a callback you register yourself with SetReadyCallback, not a fixed event name). Calling them in Form_Load is a silent no-op or fails. Two calls belong in Form_Load, after EnsureLicensed: EnableLvFacade and AddScriptToExecuteOnDocumentCreated. Before the browser exists they are queued and applied before the first page. Inside WebViewReady they fail at once with &H80040203.
  3. Host objects must be added before the navigation that uses them. Order inside the ready handler: SetLocalContentRoot → AreHostObjectsAllowed → AddHostObjectToScript → Navigate.
  4. Buttons need a MouseDown mirror when focus may be inside the browser. Keep Click for keyboard activation; add MouseDown so the first physical mouse click also fires the action. Access uses the first click on an external button to move focus, swallowing the Click event.
  5. Reg-Free teardown is required. Form_Unload must call ClearReadyCallback, DestroyBrowserSync idx, 2000, then Set pool = Nothing. Registered Mode only needs Set m_lv = Nothing in Form_Close.

Canonical setup helpers (project convention, not native COM members)

These are template helper routines the Cookbook's boilerplate ships in a shared module — not methods on LiteView2Ctrl or the pool object itself — but the lifecycle rules above depend on them, so their contract is documented here.

EnsureLicensed(ctrl) — lives in modLV2License.bas (Registered Mode). Activates the license once per process; called from every form's Form_Load. Idempotent: checks an internal flag and exits early on subsequent calls, so calling it twice (e.g. a form re-imported into another project) is harmless.

GetPool() — lives in modLV2Pool.bas (Reg-Free Mode). Returns the shared pool object and activates the license internally on its first call in the process. Also idempotent — only initializes once.

Do/don't for the underlying ActivateLicense call these helpers wrap (full ActivateLicense parameter/return documentation lives in the Licensing reference; the facts below are the ones that affect when you may call it):

Multiple browser instances — activation scope

ActivateLicense is process-wide, not per-form and not per-browser:

Recommended pattern: the activation key lives in a shared module, never duplicated across forms. Whichever form opens first in the process triggers the activation; every later form inherits the licensed state via the same shared module. You change the key once, in one file.

Anti-pattern: calling lifecycle APIs from Form_Load

VBA
' ❌ WRONG — Form_Load runs BEFORE WebView2 is ready.
' These calls silently no-op, race with init, or cause a stuck watermark.
Private Sub Form_Load()
    Set m_lv = Me.LiteView2Ctrl1.Object
    m_lv.SetLocalContentRoot CurrentProject.Path        ' ❌ wait for WebViewReady
    m_lv.AddHostObjectToScript "vba", Me                ' ❌ wait for WebViewReady
    m_lv.Navigate "https://lv2.example/index.html"      ' ❌ wait for WebViewReady
End Sub
VBA
' ✅ CORRECT — Form_Load only acquires the typed reference + activates the license.
' Activation key lives in modLV2License.bas, not duplicated here.
Private Sub Form_Load()
    Set m_lv = Me.LiteView2Ctrl1.Object
    EnsureLicensed m_lv                      ' from modLV2License — once per process
End Sub

Private Sub LiteView2Ctrl1_WebViewReady()
    m_lv.SetLocalContentRoot CurrentProject.Path
    m_lv.AreHostObjectsAllowed = True
    m_lv.AddHostObjectToScript "vba", Me
    m_lv.Navigate "https://lv2.example/index.html"
End Sub

Same anti-pattern applies to Reg-Free Mode: do Set pool = GetPool() (which activates the license internally) + CreateInControl + SetReadyCallback in Form_Load; move SetLocalContentRoot / SetAreHostObjectsAllowed / AddHostObjectToScript / Navigate into the OnBrowserReady callback.

Lifecycle timeline

Registered Mode:

Text
TIME EVENT                            WHAT YOUR CODE DOES HERE
──── ──────────────────────────────── ───────────────────────────────────────────
 t0  Form_Load                        Set m_lv = Me.LiteView2Ctrl1.Object
                                      EnsureLicensed m_lv   (from modLV2License)
 ↓
     (WebView2 starts up — async)     (you do nothing; message loop runs)
 ↓
 t1  LiteView2Ctrl1_WebViewReady      m_lv.SetLocalContentRoot CurrentProject.Path
                                      m_lv.AreHostObjectsAllowed = True
                                      m_lv.AddHostObjectToScript "vba", Me
                                      m_lv.Navigate "https://lv2.example/index.html"
 ↓
 t2  Page loads → DOMContentLoaded    JavaScript runs in the page
                                      Page calls window.chrome.webview
                                                .hostObjects.sync.vba.OnReady()
 ↓
 t3  Public Sub OnReady() in VBA      Note "page ready" / push data with ExecuteScriptAsync.
                                      Runs inside the page's call: calls that wait for
                                      the browser fail here (&H80040203)
 ↓
 t4  LiteView2Ctrl1_NavigationCompleted
                                      Post-load work that needs ExecuteScript and other
                                      synchronous calls runs here
 ↓
     (user interacts...)
 ↓
 tN  Form_Close                       Set m_lv = Nothing

Reg-Free Mode:

Text
TIME EVENT                            WHAT YOUR CODE DOES HERE
──── ──────────────────────────────── ───────────────────────────────────────────
 t0  Form_Load                        Set pool = GetPool()    (modLV2Pool activates
                                                               the license internally)
                                      idx = pool.CreateInControl("about:blank", fra)
                                      pool.SetReadyCallback idx, Me, "OnBrowserReady"
 ↓
     (WebView2 starts up — async)     (you do nothing)
 ↓
 t1  Public Sub OnBrowserReady        pool.SetLocalContentRoot idx, CurrentProject.Path
                                      pool.SetAreHostObjectsAllowed idx, True
                                      pool.AddHostObjectToScript idx, "vba", Me
                                      pool.Navigate idx, "https://lv2.example/index.html"
 ↓
 t2  Page loads → DOMContentLoaded    JavaScript runs in the page
                                      Page calls window.chrome.webview
                                                .hostObjects.sync.vba.OnReady()
 ↓
 t3  Public Sub OnReady() in VBA      Note "page ready" / push data with ExecuteScriptAsync.
                                      Runs inside the page's call: calls that wait for
                                      the browser fail here (&H80040203)
 ↓
 t4  Form_Timer                       Post-load work that needs ExecuteScript and other
                                      synchronous calls runs here
 ↓
     (user interacts...)
 ↓
 tN  Form_Unload                      pool.Stop idx
                                      pool.ClearReadyCallback idx
                                      pool.DestroyBrowserSync idx, 2000
                                      Set pool = Nothing

Exit lifecycle — closing the form safely

The loading sequence has a clear order; the unloading sequence does too. Following it cleanly prevents three real problems:

  1. A navigation in flight at the moment the form closes can fire NavigationCompleted against a half-destroyed control.
  2. An async ready callback that hasn't fired yet can trigger after VBA references are gone.
  3. Reg-Free Mode only — the WebView2 host process (msedgewebview2.exe) keeps Access alive after the form closes if it isn't explicitly torn down.

Registered Mode exit — what each line does

VBA
Private Sub Form_Close()
    On Error Resume Next
    If Not m_lv Is Nothing Then
        m_lv.Stop                  ' halt any in-flight navigation before teardown
        Set m_lv = Nothing         ' release the reference; Access destroys the control next
    End If
End Sub

Registered Mode does NOT need DestroyBrowserSync — that's a pool-only API. The control's own destructor handles the equivalent work when Access tears the form down.

Reg-Free Mode exit — what each line does

VBA
Private Sub Form_Unload(Cancel As Integer)
    On Error Resume Next
    If Not pool Is Nothing And idx <> 0 Then
        pool.Stop idx                       ' halt any in-flight navigation
        pool.ClearReadyCallback idx         ' detach our callback so it can't fire after teardown
        pool.DestroyBrowserSync idx, 2000   ' synchronous browser teardown (max 2 s wait)
        idx = 0
    End If
    Set pool = Nothing                      ' release the pool reference
End Sub

Why On Error Resume Next in the teardown

By the time Form_Close / Form_Unload fires, the form may be unloading because of an earlier error elsewhere. A second error popping a MsgBox during shutdown produces a half-stuck form customers struggle to dismiss. On Error Resume Next swallows teardown errors so the form can finish unloading — any genuine bug is caught earlier by the On Error GoTo ErrH blocks in Form_Load and OnBrowserReady.

Browser creation

CreateLifecycle and Browser Creation

Create browser. Returns index (1, 2, 3…) or 0 on error.

Signatureidx = pool.Create(hwndParent, url, x, y, width, height)
Registerednot available Reg-Freesupported
VBA
Dim idx As Long
idx = pool.Create(hwndParent, url, x, y, width, height)

CreateInControlLifecycle and Browser Creation

Create browser and embed in control — one-liner convenience method.

Signatureidx = pool.CreateInControl(url, control)
Registerednot available Reg-Freesupported
VBA
Dim idx As Long
idx = pool.CreateInControl(url, control)

CreateWithProfileLifecycle and Browser Creation

Create browser with a named profile for session isolation.

Signatureidx = pool.CreateWithProfile(hwndParent, url, x, y, width, height, profileName)
Registerednot available Reg-Freesupported
VBA
Dim idx As Long
idx = pool.CreateWithProfile(hwndParent, url, x, y, width, height, profileName)

CreateInControlWithProfileLifecycle and Browser Creation

Create browser with profile and embed in a VBA control.

Signatureidx = pool.CreateInControlWithProfile(url, control, profileName)
Registerednot available Reg-Freesupported
VBA
Dim idx As Long
idx = pool.CreateInControlWithProfile(url, control, profileName)

CreateWithProfileInPrivateLifecycle and Browser Creation

Create browser with a named profile in InPrivate mode.

Signatureidx = pool.CreateWithProfileInPrivate(hwndParent, url, x, y, width, height, profileName)
Registerednot available Reg-Freesupported
VBA
Dim idx As Long
idx = pool.CreateWithProfileInPrivate(hwndParent, url, x, y, width, height, profileName)

Embedding

EmbedInControlLifecycle and Browser Creation

Embed browser into a VBA control (Frame, Image, etc.).

Signaturepool.EmbedInControl idx, control
Registerednot available Reg-Freesupported
VBA
pool.EmbedInControl idx, control

EmbedInHwndLifecycle and Browser Creation

Embed browser in an external window handle for reg-free usage.

Signaturem_lv.EmbedInHwnd hwndParent, width, height
Registeredsupported Reg-Freeno direct equivalent
VBA
m_lv.EmbedInHwnd hwndParent, width, height

Gotchas

  • The Mode tag and the ctrl.-based signature (m_lv.EmbedInHwnd) both indicate Registered Only, but the description text says "for reg-free usage" — this wording mismatch is in the source itself and is preserved here rather than silently resolved.

EmbedInHwndByLongLifecycle and Browser Creation

Embed browser using LONG parent handle (VB6/VFP compatibility).

Signaturem_lv.EmbedInHwndByLong hwndParent, width, height
Registeredsupported Reg-Freenot available
VBA
m_lv.EmbedInHwndByLong hwndParent, width, height

Ready state

IsReadyLifecycle and Browser Creation

Check if WebView2 is ready.

Signatureresult = m_lv.IsReady() / result = pool.IsReady(idx)
Registeredsupported Reg-Freesupported
VBA
' Registered
Dim result As Boolean
result = m_lv.IsReady()
VBA
' Reg-Free
Dim result As Boolean
result = pool.IsReady(idx)

SetReadyCallbackLifecycle and Browser Creation

Register a COM callback object/method to invoke when the browser is fully ready.

callbackObject must be STA-affine (VBA form, VB6 class, etc.). Fires immediately if the browser is already ready at registration time. Fires exactly once per registration. Dispatched on the LiteView2 UI thread via PostMessage — never on WebView2 callback threads.

Signaturepool.SetReadyCallback idx, callbackObject, methodName
Registerednot available Reg-Freesupported
VBA
pool.SetReadyCallback idx, callbackObject, methodName

ClearReadyCallbackLifecycle and Browser Creation

Unregister the ready callback and allow re-registration.

Signaturepool.ClearReadyCallback idx
Registerednot available Reg-Freesupported
VBA
pool.ClearReadyCallback idx

Resizing and reparenting

ResizeLifecycle and Browser Creation

Resize browser.

Signaturepool.Resize idx, x, y, width, height
Registerednot available Reg-Freesupported
VBA
pool.Resize idx, x, y, width, height

ResizeEmbeddedLifecycle and Browser Creation

Resize the embedded browser to new dimensions.

Signaturem_lv.ResizeEmbedded width, height
Registeredsupported Reg-Freenot available
VBA
m_lv.ResizeEmbedded width, height

ReparentLifecycle and Browser Creation

Reparent browser to new window.

Signaturepool.Reparent idx, hwndNewParent, x, y, width, height
Registerednot available Reg-Freesupported
VBA
pool.Reparent idx, hwndNewParent, x, y, width, height

Parking (hide without destroying)

Park and ParkBrowser are documented separately in the source with near-identical descriptions ("Park browser (hide) by index" vs. "Park browser (hide without destroying)") and identical signatures — presented here as they appear, not merged, since the source does not state they are the same method.

ParkLifecycle and Browser Creation

Park browser (hide) by index.

Signaturepool.Park idx
Registerednot available Reg-Freesupported
VBA
pool.Park idx

Gotchas

  • Documented separately from ParkBrowser, which has a near-identical description ("Park browser (hide without destroying)") and an identical signature; the source does not state whether the two are the same underlying method.

See alsoParkBrowser

ParkBrowserLifecycle and Browser Creation

Park browser (hide without destroying).

Signaturepool.ParkBrowser idx
Registerednot available Reg-Freesupported
VBA
pool.ParkBrowser idx

Gotchas

  • Documented separately from Park, which has a near-identical description ("Park browser (hide) by index") and an identical signature; the source does not state whether the two are the same underlying method.

See alsoPark

GetParkedBrowserCountLifecycle and Browser Creation

Get count of currently parked browsers.

Signatureresult = pool.GetParkedBrowserCount()
Registerednot available Reg-Freesupported
VBA
Dim result As Long
result = pool.GetParkedBrowserCount()

Browser count and handle validity

GetBrowserCountLifecycle and Browser Creation

Get count of active browsers.

Signatureresult = pool.GetBrowserCount()
Registerednot available Reg-Freesupported
VBA
Dim result As Long
result = pool.GetBrowserCount()

IsValidHandle and IsValidIndex are likewise documented as two separate members with essentially identical descriptions ("Check if browser index is valid" vs. "Check if index is valid") and identical signatures. Presented separately below as documented.

IsValidHandleLifecycle and Browser Creation

Check if browser index is valid.

Signatureresult = pool.IsValidHandle(idx)
Registerednot available Reg-Freesupported
VBA
Dim result As Boolean
result = pool.IsValidHandle(idx)

Gotchas

  • Documented separately from IsValidIndex, which has an essentially identical description ("Check if index is valid") and an identical signature.

See alsoIsValidIndex

IsValidIndexLifecycle and Browser Creation

Check if index is valid.

Signatureresult = pool.IsValidIndex(idx)
Registerednot available Reg-Freesupported
VBA
Dim result As Boolean
result = pool.IsValidIndex(idx)

Gotchas

  • Documented separately from IsValidHandle, which has an essentially identical description ("Check if browser index is valid") and an identical signature.

See alsoIsValidHandle

Destruction

Four distinct destroy-family members are documented in the source. Destroy and DestroyBrowser have separate, near-identical descriptions ("Destroy browser by index" vs. "Destroy browser instance"); DestroySync and DestroyBrowserSync are genuinely different signatures (one takes no timeout, one does) and are NOT interchangeable — the canonical Reg-Free teardown template (see Exit Lifecycle above) uses DestroyBrowserSync specifically, not DestroySync.

DestroyLifecycle and Browser Creation

Destroy browser by index.

Signaturepool.Destroy idx
Registerednot available Reg-Freesupported
VBA
pool.Destroy idx

Gotchas

  • Documented separately from DestroyBrowser, which has a near-identical description ("Destroy browser instance").

See alsoDestroyBrowser

DestroyBrowserLifecycle and Browser Creation

Destroy browser instance.

Signaturepool.DestroyBrowser idx
Registerednot available Reg-Freesupported
VBA
pool.DestroyBrowser idx

Gotchas

  • Documented separately from Destroy, which has a near-identical description ("Destroy browser by index").

See alsoDestroy

DestroySyncLifecycle and Browser Creation

Destroy browser SYNCHRONOUSLY — pumps messages until WebView2 cleanup completes.

No timeout parameter.

Signaturepool.DestroySync idx
Registerednot available Reg-Freesupported
VBA
pool.DestroySync idx

Gotchas

  • Not interchangeable with DestroyBrowserSync — the two have genuinely different signatures (this one takes no timeout parameter); the canonical Reg-Free Form_Unload teardown pattern uses DestroyBrowserSync specifically, not this method.

See alsoDestroyBrowserSync

DestroyBrowserSyncLifecycle and Browser Creation

Destroy browser synchronously with timeout.

This is the call used in the canonical Form_Unload teardown pattern — waits up to the given millisecond timeout for in-process cleanup to complete. Without calling this during teardown, the WebView2 host process (msedgewebview2.exe) keeps running and Access cannot exit cleanly.

Signaturepool.DestroyBrowserSync idx, timeoutMs
Registerednot available Reg-Freesupported
VBA
pool.DestroyBrowserSync idx, timeoutMs
' Canonical usage:
pool.DestroyBrowserSync idx, 2000

See alsoDestroySync

DestroyAllParkedLifecycle and Browser Creation

Destroy all parked browsers — cleanup resources.

Signatureresult = pool.DestroyAllParked()
Registerednot available Reg-Freesupported
VBA
Dim result As Long
result = pool.DestroyAllParked()

Suspend / Resume

TrySuspend and SuspendBrowser are explicitly documented as aliases ("SuspendBrowser ... same as TrySuspend"). Resume and ResumeBrowser are documented the same way (the TrySuspend entry itself lists SuspendBrowser as an "Or:" alternative, and the Resume entry lists ResumeBrowser as an "Or:" alternative).

TrySuspendLifecycle and Browser Creation

Suspend the browser to reduce CPU/memory usage.

Signaturem_lv.TrySuspend / pool.TrySuspend idx
Registeredsupported Reg-Freesupported
VBA
' Registered
m_lv.TrySuspend
VBA
' Reg-Free
pool.TrySuspend idx
' Or: pool.SuspendBrowser idx

Gotchas

  • SuspendBrowser is documented as an alias for this method in Reg-Free Mode — pool.SuspendBrowser idx is shown as an "Or:" alternative to pool.TrySuspend idx.

See alsoSuspendBrowser

SuspendBrowserLifecycle and Browser Creation

Suspend browser to reduce CPU/memory (same as TrySuspend).

Use with ResumeBrowser.

Signaturepool.SuspendBrowser idx
Registerednot available Reg-Freesupported
VBA
pool.SuspendBrowser idx

See alsoTrySuspend, ResumeBrowser

ResumeLifecycle and Browser Creation

Resume a suspended browser.

Signaturem_lv.Resume / pool.Resume idx
Registeredsupported Reg-Freesupported
VBA
' Registered
m_lv.Resume
VBA
' Reg-Free
pool.Resume idx
' Or: pool.ResumeBrowser idx

Gotchas

  • ResumeBrowser is documented as an alias for this method in Reg-Free Mode — pool.ResumeBrowser idx is shown as an "Or:" alternative to pool.Resume idx.

See alsoResumeBrowser

ResumeBrowserLifecycle and Browser Creation

Resume browser.

Signaturepool.ResumeBrowser idx
Registerednot available Reg-Freesupported
VBA
pool.ResumeBrowser idx

See alsoResume

IsSuspendedLifecycle and Browser Creation

Check if the browser is suspended.

Type: Boolean. Read-only.

Signaturem_lv.IsSuspended / pool.IsSuspended(idx)
Registeredsupported Reg-Freesupported
VBA
' Registered
If m_lv.IsSuspended Then m_lv.Resume
VBA
' Reg-Free
If pool.IsSuspended(idx) Then pool.Resume idx

Resource control

DisposeLifecycle and Browser Creation

Explicitly release all WebView resources.

Signaturem_lv.Dispose / pool.Dispose idx
Registeredsupported Reg-Freesupported
VBA
' Registered
m_lv.Dispose
Set m_lv = Nothing
VBA
' Reg-Free
pool.Dispose idx

CloseBrowserProcessLifecycle and Browser Creation

Force close the browser process.

Signaturem_lv.CloseBrowserProcess / pool.CloseBrowserProcess idx
Registeredsupported Reg-Freesupported
VBA
' Registered
m_lv.CloseBrowserProcess
VBA
' Reg-Free
pool.CloseBrowserProcess idx

GetMemoryUsageLifecycle and Browser Creation

Get approximate memory usage in bytes.

Signaturem_lv.GetMemoryUsage / pool.GetMemoryUsage(idx)
Registeredsupported Reg-Freesupported
VBA
' Registered
Debug.Print "Memory: " & Format(m_lv.GetMemoryUsage / 1048576, "0.0") & " MB"
VBA
' Reg-Free
Debug.Print "Memory: " & Format(pool.GetMemoryUsage(idx) / 1048576, "0.0") & " MB"

ForceGarbageCollectionLifecycle and Browser Creation

Force JavaScript garbage collection.

Signaturem_lv.ForceGarbageCollection / pool.ForceGarbageCollection idx
Registeredsupported Reg-Freesupported
VBA
' Registered
m_lv.ForceGarbageCollection
VBA
' Reg-Free
pool.ForceGarbageCollection idx

Focus, window notification, and debugging

MoveFocusLifecycle and Browser Creation

Move focus into or out of the WebView.

Signaturem_lv.MoveFocus 0 / pool.MoveFocus idx, 0
Registeredsupported Reg-Freesupported
VBA
' Registered
m_lv.MoveFocus 0   ' LV2_FOCUS_TABFORWARD
m_lv.MoveFocus 2   ' LV2_FOCUS_PROGRAMMATIC
VBA
' Reg-Free
pool.MoveFocus idx, 0

NotifyParentWindowPositionChangedLifecycle and Browser Creation

Notify WebView that the host window has moved (fixes DPI/rendering).

Signaturem_lv.NotifyParentWindowPositionChanged
Registeredsupported Reg-Freehandled internally
VBA
' Registered
m_lv.NotifyParentWindowPositionChanged
VBA
' Reg-Free
' Not available in pool - handled internally

Gotchas

  • Explicitly not available in the Reg-Free pool — the source states it is "handled internally" there, with no equivalent call to make yourself.

ToggleBridgeInspectorLifecycle and Browser Creation

Toggle Bridge Inspector HUD showing live JS <-> VBA message traffic.

Signaturem_lv.ToggleBridgeInspector / pool.ToggleBridgeInspector idx
Registeredsupported Reg-Freesupported
VBA
' Registered
m_lv.ToggleBridgeInspector
VBA
' Reg-Free
pool.ToggleBridgeInspector idx

Diagnostics and Read-Only Status Properties

The following read-only/diagnostic members were confirmed present in the source but not captured under any category during the first drafting pass; added here during the completeness audit so Part II remains an exhaustive reference. All are documented with the Reg-Free forms shown exactly as the source gives them.

GetDiagnosticsLifecycle and Browser Creation

Get diagnostic information about the WebView state.

Signaturem_lv.GetDiagnostics
Registeredsupported Reg-Freenot available — use GetLastError instead
VBA
' Registered
Debug.Print m_lv.GetDiagnostics
VBA
' Reg-Free
' Not available in pool - use GetLastError instead

Gotchas

  • Reg-Free Mode has no equivalent call — use GetLastError / GetLastErrorCode instead.

See alsoLastError, LastErrorCode

IsVisibleLifecycle and Browser Creation

Get or set WebView visibility.

Type: Boolean. R/W.

Signaturem_lv.IsVisible = True / pool.SetIsVisible idx, True
Registeredsupported Reg-Freedocumented two ways
VBA
' Registered
m_lv.IsVisible = False   ' Hide
m_lv.IsVisible = True    ' Show
VBA
' Reg-Free
pool.SetVisible idx, False
pool.SetIsVisible idx, True
Dim visible As Boolean
visible = pool.GetIsVisible(idx)

Gotchas

  • The source shows two different Reg-Free setter names for the same property, SetVisible and SetIsVisible, side by side in the same example, with no explanation of which is authoritative or whether they're aliases. Both are preserved here exactly as documented; verify against your installed type library before relying on either.

BrowserProcessId / BrowserProcessIDLongLifecycle and Browser Creation

Get the browser subprocess process ID.

Type: Long. Read-only. BrowserProcessIDLong is a VB6-friendly alias for BrowserProcessId.

Signaturem_lv.BrowserProcessId / pool.GetBrowserProcessId(idx)
Registeredsupported Reg-Freesupported
VBA
' Registered
Debug.Print "PID: " & m_lv.BrowserProcessId
Debug.Print "PID (Long): " & m_lv.BrowserProcessIDLong
VBA
' Reg-Free
Debug.Print "PID: " & pool.GetBrowserProcessId(idx)

Gotchas

  • Reg-Free Mode exposes only the plain (non-Long-suffixed) form, pool.GetBrowserProcessId(idx) — there is no Reg-Free equivalent to the VB6-friendly BrowserProcessIDLong alias.

ContainsFullScreenElementLifecycle and Browser Creation

Whether the page has a fullscreen element.

Type: Boolean. Read-only.

Signaturem_lv.ContainsFullScreenElement / pool.GetContainsFullScreenElement(idx)
Registeredsupported Reg-Freesupported
VBA
' Registered
If m_lv.ContainsFullScreenElement Then Debug.Print "Fullscreen active"
VBA
' Reg-Free
If pool.GetContainsFullScreenElement(idx) Then Debug.Print "Fullscreen"

See alsoContainsFullScreenElementChanged (event, Events — Registered Mode)

StatusBarTextLifecycle and Browser Creation

Current status bar text.

Type: String. Read-only.

Signaturem_lv.StatusBarText / pool.GetStatusBarText(idx)
Registeredsupported Reg-Freesupported
VBA
' Registered
Debug.Print m_lv.StatusBarText
VBA
' Reg-Free
Debug.Print pool.GetStatusBarText(idx)

See alsoStatusBarTextChanged (event, Events — Registered Mode)

LastError / LastErrorCodeLifecycle and Browser Creation

Get the last error message and code.

Read-only.

LastErrorCode (Long, read-only) holds the HRESULT of the last failure that records one: WebView2 creation failures, an ExecuteScript / ExecuteScriptWithResult timeout (&H800705B4), or a call refused inside an event or host-object call (&H80040203). It is not reset by later successful calls, and many other failures don't set it. Handle Err at the call site and read LastErrorCode / LastError right after a failing call; don't poll it.

Signaturem_lv.LastError / pool.GetLastError(idx)
Registeredsupported Reg-Freesupported
VBA
' Registered
Debug.Print "Error: " & m_lv.LastError
Debug.Print "Code: " & m_lv.LastErrorCode
VBA
' Reg-Free
Debug.Print "Error: " & pool.GetLastError(idx)
Debug.Print "Code: " & pool.GetLastErrorCode(idx)

WebViewCreatedLifecycle and Browser Creation

Whether the WebView has been created.

Type: Boolean. Read-only.

Signaturem_lv.WebViewCreated / pool.GetWebViewCreated(idx)
Registeredsupported Reg-Freesupported
VBA
' Registered
Debug.Print "Created: " & m_lv.WebViewCreated
VBA
' Reg-Free
Debug.Print "Created: " & pool.GetWebViewCreated(idx)

FaviconUriLifecycle and Browser Creation

Favicon URI of the current page.

Type: String. Read-only.

Signaturem_lv.FaviconUri / pool.GetFaviconUri(idx)
Registeredsupported Reg-Freesupported
VBA
' Registered
Debug.Print "Favicon: " & m_lv.FaviconUri
VBA
' Reg-Free
Debug.Print "Favicon: " & pool.GetFaviconUri(idx)

See alsoFaviconChanged (event, Events — Registered Mode)

ControlVersionLifecycle and Browser Creation

Get the control version string.

Type: String. Read-only.

Signaturem_lv.ControlVersion / pool.ControlVersion
Registeredsupported Reg-Freesupported
VBA
' Registered
Debug.Print "Version: " & m_lv.ControlVersion
VBA
' Reg-Free
Debug.Print "Version: " & pool.ControlVersion

Gotchas

  • The Reg-Free form is pool.ControlVersion, a bare property with no browser index — unlike the other members in this group, which all take idx. Preserved exactly as documented.

BrowserVersionStringLifecycle and Browser Creation

Get the WebView2 runtime version.

Type: String. Read-only.

Signaturem_lv.BrowserVersionString / pool.GetBrowserVersionString(idx)
Registeredsupported Reg-Freesupported
VBA
' Registered
Debug.Print "Runtime: " & m_lv.BrowserVersionString
VBA
' Reg-Free
Debug.Print "Runtime: " & pool.GetBrowserVersionString(idx)

UserDataFolderLifecycle and Browser Creation

Get the user data folder path.

Type: String. Read-only.

Signaturem_lv.UserDataFolder / pool.GetUserDataFolder(idx)
Registeredsupported Reg-Freesupported
VBA
' Registered
Debug.Print "UDF: " & m_lv.UserDataFolder
VBA
' Reg-Free
Debug.Print "UDF: " & pool.GetUserDataFolder(idx)

InPrivateModeLifecycle and Browser Creation

Whether the browser is in InPrivate mode.

Type: Boolean. Read-only.

Signaturem_lv.InPrivateMode / pool.IsInPrivateMode(idx)
Registeredsupported Reg-Freesupported
VBA
' Registered
Debug.Print "InPrivate: " & m_lv.InPrivateMode
VBA
' Reg-Free
Debug.Print "InPrivate: " & pool.IsInPrivateMode(idx)

Gotchas

  • The Reg-Free accessor is named IsInPrivateMode, not the Get-prefixed GetInPrivateMode pattern used by sibling properties in this group.

IsDocumentPlayingAudio / IsMutedLifecycle and Browser Creation

Reg-Free only for direct get/set.

In Registered Mode, the source documents no direct properties for these — use the IsDocumentPlayingAudioChanged and IsMutedChanged events instead (see Events (Registered Mode)).

Signaturepool.GetIsDocumentPlayingAudio(idx) / pool.GetIsMuted(idx) / pool.SetIsMuted idx, True
Registeredno direct properties — use events instead Reg-Freesupported
VBA
' Reg-Free
Debug.Print "Playing: " & pool.GetIsDocumentPlayingAudio(idx)
Debug.Print "Muted: " & pool.GetIsMuted(idx)
pool.SetIsMuted idx, True   ' Mute

See alsoIsDocumentPlayingAudioChanged, IsMutedChanged (events, Events — Registered Mode)

Setup and DPI Helpers

QuickInitInFrameLifecycle and Browser Creation

Quick initialization in a Frame control (handles DPI automatically).

Signaturem_lv.QuickInitInFrame Me, Me.FraBrowser / pool.QuickInitInFrame idx, Me, Me.FraBrowser
Registeredsupported Reg-Freesupported
VBA
' Registered
m_lv.QuickInitInFrame Me, Me.FraBrowser
VBA
' Reg-Free
pool.QuickInitInFrame idx, Me, Me.FraBrowser

GetDefaultOcxPathLifecycle and Browser Creation

Get the default OCX file path for the current Office application.

Signaturem_lv.GetDefaultOcxPath / pool.GetDefaultOcxPath(idx)
Registeredsupported Reg-Freesupported
VBA
' Registered
Debug.Print m_lv.GetDefaultOcxPath
VBA
' Reg-Free
Debug.Print pool.GetDefaultOcxPath(idx)

PointsToPixelsLifecycle and Browser Creation

Convert points to pixels for DPI awareness.

Signaturepx = m_lv.PointsToPixels(100, True) / px = pool.PointsToPixels(idx, 100, True)
Registeredsupported Reg-Freesupported
VBA
' Registered
Dim px As Long
px = m_lv.PointsToPixels(100, True)  ' 100 points, horizontal axis
Debug.Print "100 points = " & px & " pixels"
VBA
' Reg-Free
Dim px As Long
px = pool.PointsToPixels(idx, 100, True)

SetLocalContentRootNavigation

Map a local folder to the fixed lv2.example virtual hostname, so local HTML/JS/CSS files can be loaded via https://lv2.example/... URLs instead of file://.

SetLocalContentRoot is a first-class IBrowserPool method (verified against the LiteView2 IDL and its C++ implementation) — it is not a Registered-only convenience. Internally it wraps SetVirtualHostNameToFolderMapping with the fixed lv2.example hostname; calling SetVirtualHostNameToFolderMapping directly does the same thing and remains available if you want a different hostname.

Signaturem_lv.SetLocalContentRoot folder
Registeredsupported Reg-Freesupported

Registered:

VBA
m_lv.SetLocalContentRoot CurrentProject.Path & "\html"
m_lv.Navigate "https://lv2.example/index.html"

Reg-Free:

VBA
pool.SetLocalContentRoot idx, CurrentProject.Path & "\html"
pool.Navigate idx, "https://lv2.example/index.html"

Gotchas

  • Ordering requirement (critical): SetLocalContentRoot must be called BEFORE the first Navigate — and before AddHostObjectToScript if host objects are used.
  • It belongs in the ready handler (LiteView2Ctrl1_WebViewReady in Registered Mode, OnBrowserReady in Reg-Free Mode), not in Form_Load. Calling it in Form_Load is a silent no-op or fails.
  • The required order inside the ready handler is: SetLocalContentRoot → AreHostObjectsAllowed → AddHostObjectToScript → Navigate.

See alsoSetVirtualHostNameToFolderMapping, NavigateToLocalFile

SetLocalContentRoot path mappingNavigation

SetLocalContentRoot folder maps a folder on disk to the https://lv2.example/ virtual host. The mapping is one-to-one: the folder you pass becomes the URL root.

Disk path you passURL rootExample file on diskURL to navigate to
C:\Apps\MyDB\https://lv2.example/C:\Apps\MyDB\index.htmlhttps://lv2.example/index.html
C:\Apps\MyDB\https://lv2.example/C:\Apps\MyDB\pages\admin.htmlhttps://lv2.example/pages/admin.html
CurrentProject.Path (e.g. C:\Apps\MyDB)https://lv2.example/the form's folderhttps://lv2.example/<any-file-in-that-folder>

Gotchas

  • Wrong root level. You map C:\Apps\ but your HTML lives in C:\Apps\MyDB\index.html. The URL must then be https://lv2.example/MyDB/index.html, not /index.html. Pick the folder that DIRECTLY contains your HTML; do not over-shoot to a parent.
  • Subfolder confusion. You pass CurrentProject.Path & "\html" and then navigate to https://lv2.example/html/index.html. The \html part already became the new root — the correct URL is https://lv2.example/index.html, with no html prefix.
  • Backslash in URL. https://lv2.example/index.html works; https://lv2.example\index.html does not. Use forward slashes in URLs only.
  • Missing target file. The mapping is correct but index.html doesn't actually exist in the mapped folder. WebView2 shows its own "page can't be reached" error — looks like a LiteView2 problem but isn't. Verify the file is there before blaming the control.

See alsoSetLocalContentRoot

SetVirtualHostNameToFolderMappingNavigation

Map a local folder to a custom (caller-chosen) virtual hostname — the general-purpose form of SetLocalContentRoot, which is hardcoded to the lv2.example hostname.

Use this instead of SetLocalContentRoot when you specifically need a hostname other than lv2.example.

Signaturem_lv.SetVirtualHostNameToFolderMapping hostName, folderPath, accessKind
Registeredsupported Reg-Freesupported

Registered:

VBA
m_lv.SetVirtualHostNameToFolderMapping "myapp.local", _
    CurrentProject.Path & "\html", 1
m_lv.Navigate "https://myapp.local/dashboard.html"

Reg-Free:

VBA
pool.SetVirtualHostNameToFolderMapping idx, "myapp.local", _
    CurrentProject.Path & "\html", 1
pool.Navigate idx, "https://myapp.local/dashboard.html"

See alsoSetLocalContentRoot, NavigateToLocalFile

ClearVirtualHostNameToFolderMappingNavigation

Remove a virtual hostname mapping previously created with SetVirtualHostNameToFolderMapping.

Signaturem_lv.ClearVirtualHostNameToFolderMapping hostName
Registeredsupported Reg-Freesupported

Registered:

VBA
m_lv.ClearVirtualHostNameToFolderMapping "myapp.local"

Reg-Free:

VBA
pool.ClearVirtualHostNameToFolderMapping idx, "myapp.local"

See alsoSetVirtualHostNameToFolderMapping

AddCustomSchemeRegistrationNavigation

Register a custom URI scheme (e.g. myapp://).

Second parameter is treatAsSecure (Boolean).

Signaturem_lv.AddCustomSchemeRegistration schemeName, treatAsSecure
Registeredsupported Reg-Freesupported

Registered:

VBA
m_lv.AddCustomSchemeRegistration "myapp", True  ' treatAsSecure

Reg-Free:

VBA
pool.AddCustomSchemeRegistration idx, "myapp", True

CreateWebResourceRequestNavigation

Create a custom HTTP request object.

Returns a handle (Long) for use with NavigateWithCustomRequest / NavigateWithWebResourceRequestSync.

SignaturehReq = m_lv.CreateWebResourceRequest(method, url, headers, postData)
Registeredsupported Reg-Freesupported

Registered:

VBA
Dim hReq As Long
hReq = m_lv.CreateWebResourceRequest("GET", "https://api.example.com/data", _
    "Authorization: Bearer token123", "")
Debug.Print "Request handle: " & hReq

Reg-Free:

VBA
Dim hReq As Long
hReq = pool.CreateWebResourceRequest(idx, "GET", "https://api.example.com/data", _
    "Authorization: Bearer token123", "")

See alsoNavigateWithCustomRequest, NavigateWithWebResourceRequestSync

CreateWebResourceResponseNavigation

Create a custom HTTP response object, for use inside a WebResourceRequested event handler.

SignaturehResp = m_lv.CreateWebResourceResponse(content, statusCode, reasonPhrase, headers)
Registeredsupported Reg-Freesupported

Registered:

VBA
Dim hResp As Long
hResp = m_lv.CreateWebResourceResponse("<h1>Blocked</h1>", 403, "Forbidden", _
    "Content-Type: text/html")

Reg-Free:

VBA
Dim hResp As Long
hResp = pool.CreateWebResourceResponse(idx, "<h1>Blocked</h1>", 403, "Forbidden", _
    "Content-Type: text/html")

See alsoWebResourceRequested

GoBack / CanGoBackNavigation

GoBack navigates back in history. CanGoBack (Property, Boolean, read-only) reports whether a back-navigation is currently possible.

SignatureIf m_lv.CanGoBack Then m_lv.GoBack
Registeredsupported Reg-Freesupported

Registered:

VBA
If m_lv.CanGoBack Then m_lv.GoBack
Debug.Print "Can go back: " & m_lv.CanGoBack

Reg-Free:

VBA
If pool.CanGoBack(idx) Then pool.GoBack idx
Debug.Print "Can go back: " & pool.CanGoBack(idx)

GoForward / CanGoForwardNavigation

GoForward navigates forward in history. CanGoForward (Property, Boolean, read-only) reports whether a forward-navigation is currently possible.

SignatureIf m_lv.CanGoForward Then m_lv.GoForward
Registeredsupported Reg-Freesupported

Registered:

VBA
If m_lv.CanGoForward Then m_lv.GoForward
Debug.Print "Can go forward: " & m_lv.CanGoForward

Reg-Free:

VBA
If pool.CanGoForward(idx) Then pool.GoForward idx
Debug.Print "Can go forward: " & pool.CanGoForward(idx)

RefreshNavigation

Reload the current page.

Signaturem_lv.Refresh
Registeredsupported Reg-Freesupported

Registered:

VBA
m_lv.Refresh

Reg-Free:

VBA
pool.Refresh idx

StopNavigation

Stop loading the current page.

Signaturem_lv.Stop
Registeredsupported Reg-Freesupported

Registered:

VBA
m_lv.Stop   ' halt any in-flight navigation before teardown

Reg-Free:

VBA
pool.Stop idx   ' halt any in-flight navigation before teardown

Gotchas

  • Documented elsewhere in the source as a required teardown call — call it in Form_Unload to halt any in-flight navigation before the control/pool slot is destroyed.
  • Without it, the page can fire NavigationCompleted while the control is being torn down.

See alsoNavigationCompleted

Url (Property)Navigation

Get or set the current URL.

Type: String. Registered Mode: read/write (setting it navigates, same as calling Navigate). Reg-Free Mode: the pool exposes only a getter (GetUrl) — there is no Url property setter in the pool object; use Navigate to change the URL instead.

Signaturem_lv.Url [= url]
Registeredread/write Reg-Freeread-only (GetUrl)

Registered:

VBA
Debug.Print m_lv.Url              ' Get current URL
m_lv.Url = "https://example.com"  ' Navigate (same as Navigate)

Reg-Free:

VBA
Debug.Print pool.GetUrl(idx)          ' Get current URL
pool.Navigate idx, "https://example.com"  ' No Url property setter in pool

Gotchas

  • GetUrl is separately documented in the auto-synced API reference as Mode: Reg-Free Only — "Get current URL" — result = pool.GetUrl(idx) — consistent with the Registered/Reg-Free pairing shown here.

See alsoGetUrl, Navigate

DocumentTitle (Property) / GetTitleNavigation

Get the current page title.

Type: String. Read-only in both modes. In Registered Mode this is the DocumentTitle property; in Reg-Free Mode there is no DocumentTitle property on the pool — use the GetTitle method instead.

Signaturem_lv.DocumentTitle
Registeredsupported Reg-Freesupported (GetTitle)

Registered:

VBA
Debug.Print "Title: " & m_lv.DocumentTitle

Reg-Free:

VBA
Debug.Print "Title: " & pool.GetTitle(idx)

Gotchas

  • GetTitle is separately documented in the auto-synced API reference as Mode: Reg-Free Only — "Get page title" — result = pool.GetTitle(idx) — consistent with the pairing shown here.

See alsoGetTitle

IsLoading (Property)Navigation

Check if the page is currently loading.

Type: Boolean. Read-only.

Signaturem_lv.IsLoading
Registeredsupported Reg-Freesupported

Registered:

VBA
If m_lv.IsLoading Then Debug.Print "Still loading..."

Reg-Free:

VBA
If pool.IsLoading(idx) Then Debug.Print "Still loading..."

SynchronousTimeOut (Property)Navigation

SynchronousTimeOut is the timeout, in milliseconds (default 30000), that ExecuteScript (with everything built on it), ExecuteScriptWithResult, the three *Sync navigation methods and WaitForElement (when you pass 0 for its timeoutMs) wait before giving up.

Type: Long. Read/write. The UI remains responsive during the wait (message pump).

Use a value greater than 0.

  • ExecuteScript and ExecuteScriptWithResult treat 0 as 30000.
  • The *Sync navigation methods treat 0 as "don't wait": they return the timeout error &H800705B4 at once, while the navigation goes on.

On a timeout, ExecuteScript and the *Sync methods raise &H800705B4, and ExecuteScriptWithResult returns succeeded = False.

Other waiting calls have fixed limits and ignore this property:

CallFixed limit
CallScriptSync, GetScriptProperty, SetScriptProperty, BindScriptObject with Validate30 s (LV2_BRIDGE_TIMEOUT, &H80040507)
CallDevToolsProtocolMethod, ClearBrowsingDataInTimeRange30 s
GetBrowserExtensionList, DetectCaptcha10 s
GetCookies, AddScriptToExecuteOnDocumentCreated5 s

Inside inline events and host-object calls no wait starts at all: the call fails at once with &H80040203. A negative value raises E_INVALIDARG.

Signaturem_lv.SynchronousTimeOut [= ms]
Registeredsupported Reg-Freesupported

Registered:

VBA
Debug.Print m_lv.SynchronousTimeOut       ' Get (default 30000)
m_lv.SynchronousTimeOut = 60000           ' Set to 60 seconds

Reg-Free:

VBA
Debug.Print pool.SynchronousTimeOut(idx)
pool.SynchronousTimeOut(idx) = 60000

See alsoNavigateSync, NavigateToStringSync

Local Content and Virtual Hosts

SetLocalContentRootLocal Content and Virtual Hosts

Maps a folder on disk to the reserved https://lv2.example/ virtual host.

The mapping is one-to-one: the folder you pass becomes the URL root. Verified against the LiteView2 IDL and its C++ implementation: IBrowserPool.SetLocalContentRoot(browserIndex, folderPath) is a first-class pool method, not a Registered-only convenience — internally it wraps SetVirtualHostNameToFolderMapping with the fixed lv2.example hostname on either side.

SignatureSetLocalContentRoot([idx,] folderPath)
Registeredsupported Reg-Freesupported
VBA
m_lv.SetLocalContentRoot CurrentProject.Path & "\html"
m_lv.Navigate "https://lv2.example/index.html"
VBA
pool.SetLocalContentRoot idx, CurrentProject.Path & "\html"
pool.Navigate idx, "https://lv2.example/index.html"

Path-mapping examples

Disk path you passURL rootExample file on diskURL to navigate to
C:\Apps\MyDB\https://lv2.example/C:\Apps\MyDB\index.htmlhttps://lv2.example/index.html
C:\Apps\MyDB\https://lv2.example/C:\Apps\MyDB\pages\admin.htmlhttps://lv2.example/pages/admin.html
CurrentProject.Path (e.g. C:\Apps\MyDB)https://lv2.example/the form's folderhttps://lv2.example/<any-file-in-that-folder>

Gotchas

  • Wrong root level. You map C:\Apps\ but your HTML lives in C:\Apps\MyDB\index.html. The URL must then be https://lv2.example/MyDB/index.html, not /index.html. Pick the folder that DIRECTLY contains your HTML; do not over-shoot to a parent.
  • Subfolder confusion. You pass CurrentProject.Path & "\html" and then navigate to https://lv2.example/html/index.html. The \html part already became the new root — the correct URL is https://lv2.example/index.html, with no html prefix.
  • Backslash in URL. https://lv2.example/index.html works; https://lv2.example\index.html does not. Use forward slashes in URLs only.
  • Missing target file. The mapping is correct but index.html doesn't actually exist in the mapped folder. WebView2 shows its own "page can't be reached" error — looks like a LiteView2 problem but isn't. Verify the file is there before blaming the control.

See alsoSetVirtualHostNameToFolderMapping

SetVirtualHostNameToFolderMappingLocal Content and Virtual Hosts

Maps a local folder to a custom virtual hostname (any hostname you choose, not limited to lv2.example).

SignatureSetVirtualHostNameToFolderMapping([idx,] hostName, folderPath, 1)
Registeredsupported Reg-Freesupported
VBA
m_lv.SetVirtualHostNameToFolderMapping "myapp.local", _
    CurrentProject.Path & "\html", 1
m_lv.Navigate "https://myapp.local/dashboard.html"
VBA
pool.SetVirtualHostNameToFolderMapping idx, "myapp.local", _
    CurrentProject.Path & "\html", 1
pool.Navigate idx, "https://myapp.local/dashboard.html"

Gotchas

  • In Reg-Free the call takes idx as the leading browser-index argument; Registered has no such argument, since m_lv addresses a single control instance directly.
  • Both forms pass a trailing 1 as the final argument, exactly as shown in the source examples; the reviewed source ranges do not define what that argument represents.

See alsoSetLocalContentRoot

ClearVirtualHostNameToFolderMappingLocal Content and Virtual Hosts

Removes a virtual hostname mapping previously set with SetVirtualHostNameToFolderMapping (or SetLocalContentRoot).

SignatureClearVirtualHostNameToFolderMapping([idx,] hostName)
Registeredsupported Reg-Freesupported
VBA
m_lv.ClearVirtualHostNameToFolderMapping "myapp.local"
VBA
pool.ClearVirtualHostNameToFolderMapping idx, "myapp.local"

See alsoSetVirtualHostNameToFolderMapping, SetLocalContentRoot

AddCustomSchemeRegistrationLocal Content and Virtual Hosts

Registers a custom URI scheme (e.g., myapp://).

SignatureAddCustomSchemeRegistration([idx,] schemeName, treatAsSecure)
Registeredsupported Reg-Freesupported
VBA
m_lv.AddCustomSchemeRegistration "myapp", True  ' treatAsSecure
VBA
pool.AddCustomSchemeRegistration idx, "myapp", True

Script Execution

Synchronous calls and events (LiteView2 1.0.1.0)

Which calls wait. Some methods wait for the browser's answer before they return:

  • ExecuteScript and everything built on it: ExecuteScriptWithArgs, the DOM helpers such as GetElementValueById, GetPageHtml, GetPageText and GetTextBySelector
  • ExecuteScriptWithResult, WaitForElement, GetCookies, GetBrowserExtensionList, ClearBrowsingDataInTimeRange, CallDevToolsProtocolMethod, DetectCaptcha, SolveCaptcha
  • NavigateSync, NavigateToStringSync, NavigateWithWebResourceRequestSync
  • CallScriptSync, GetScriptProperty, SetScriptProperty, and BindScriptObject with LV2_BIND_VALIDATE
  • once the browser exists: AddScriptToExecuteOnDocumentCreated and EnableLvFacade

Where they work. In ordinary code (a button, a timer), and inside these events, which LiteView2 raises after WebView2's own callback has returned:

  • NavigationCompleted, NavigationCompletedHex
  • SourceChanged, ContentLoading, ContentLoadingHex, DOMContentLoaded
  • DocumentTitleChanged, HistoryChanged
  • WebMessageReceived, DevToolsProtocolEventReceived

Where they fail. Everywhere else they do not wait. They fail at once with error &H80040203 (-2147220989), start nothing, and the error text says what to use instead. That applies:

  • inside WebViewReady, CreateWebViewCompleted, NavigationStarting and every other event not listed above;
  • inside a VBA method the page is calling through a host object (chrome.webview.hostObjects.<name> or .sync.<name>) or RegisterVbaCallback.

WaitForElement returns False there instead of raising. The rule is per thread: inside one control's event, the other LiteView2 controls on the form refuse as well.

What to use in those places. Calls that do not wait: Navigate, NavigateToString, ExecuteScriptAsync, PostWebMessageAsJson / PostWebMessageAsString, CallScript, PushRecordset, FireJsEvent, CallJsFunction, SetJsVariable, AddHostObjectToScript, property assignments, and the JSON helpers. To get a value back, do one of these:

  • return it from the host-object method;
  • let the page answer with chrome.webview.postMessage(...) and read the answer in WebMessageReceived;
  • make the call after the handler has returned: a form Timer in Access, Application.OnTime in Excel or Word, a Timer control in VB6.

Reg-Free (BrowserPool). The pool raises no events. Its ready callback (SetReadyCallback) and message macro (SetWebMessageCallback) run from the message loop, where synchronous pool calls work. The exception is when your own code is pumping messages (MsgBox, DoEvents) inside an event or host-object method at that moment. Inside a VBA method the page is calling, a synchronous pool call fails with &H80004005; pool.GetLastErrorCode(idx) returns &H80040203 and pool.GetLastError(idx) gives the reason.

ExecuteScriptScript Execution

Execute JavaScript synchronously and return the result as a JSON-encoded string.

Waits at most SynchronousTimeOut ms (default 30000; 0 also means 30000). On a timeout it raises &H800705B4 (-2147023436) and sets LastErrorCode; the page may still run the script later. Inside WebViewReady, NavigationStarting, the other inline events and host-object methods it raises &H80040203 at once and runs nothing. Use ExecuteScriptAsync there. It works inside NavigationCompleted, DOMContentLoaded, WebMessageReceived and the other notification events. Before the browser exists it fails: it is not queued (ExecuteScriptAsync is).

Reg-Free: a failing call raises &H80004005; pool.GetLastErrorCode(idx) returns &H80040203 or &H800705B4.

Signatureresult = m_lv.ExecuteScript(script)
Registeredsupported Reg-Freesupported
VBA
Dim result As String
result = m_lv.ExecuteScript("document.title")
Debug.Print "Title: " & result  ' Returns JSON-encoded: "My Page Title"

' Call a function
result = m_lv.ExecuteScript("getFormData()")
Debug.Print result  ' Returns: {"name":"John Doe","email":"john@example.com"}
VBA
Dim result As String
result = pool.ExecuteScript(idx, "document.title")
Debug.Print "Title: " & result

ExecuteScriptAsyncScript Execution

Execute JavaScript asynchronously (fire and forget). No return value.

Signaturem_lv.ExecuteScriptAsync script
Registeredsupported Reg-Freesupported
VBA
m_lv.ExecuteScriptAsync "updateStatus('Processing...');"
m_lv.ExecuteScriptAsync "document.getElementById('divResults').textContent = 'Updated';"
VBA
pool.ExecuteScriptAsync idx, "updateStatus('Processing...');"

ExecuteScriptWithResultScript Execution

Execute script and get result + success flag + exception info.

Waits at most SynchronousTimeOut (0 means 30000). A timeout raises no error. Instead it returns succeeded = False, puts "ExecuteScriptWithResult got no result from the page within … ms (SynchronousTimeOut)…" in errMsg, and sets LastErrorCode = &H800705B4. So succeeded = False does not always mean the script threw. Inside inline events and host-object methods it raises &H80040203 (it does not return succeeded = False) and runs nothing.

Signaturem_lv.ExecuteScriptWithResult script, resultJson, succeeded, errMsg
Registeredsupported Reg-Freesupported
VBA
Dim resultJson As String, succeeded As Boolean, errMsg As String
m_lv.ExecuteScriptWithResult "1 + 2", resultJson, succeeded, errMsg
If succeeded Then
    Debug.Print "Result: " & resultJson   ' "3"
Else
    Debug.Print "Error: " & errMsg
End If
VBA
Dim resultJson As String, succeeded As Boolean, errMsg As String
pool.ExecuteScriptWithResult idx, "1 + 2", resultJson, succeeded, errMsg
If succeeded Then Debug.Print "Result: " & resultJson

ExecuteScriptWithArgsScript Execution

Execute a JavaScript function with VBA arguments (auto-serialized).

Signatureresult = m_lv.ExecuteScriptWithArgs(funcName, argsArray)
Registeredsupported Reg-Freesupported
VBA
Dim result As String
result = m_lv.ExecuteScriptWithArgs("loadKpis", Array(100, 50))
' Calls: loadKpis(100, 50) in the page
VBA
Dim result As String
result = pool.ExecuteScriptWithArgs(idx, "loadKpis", Array(100, 50))

CallJsFunctionScript Execution

Call a JavaScript function by dot-path with a JSON-encoded arguments array.

Signaturem_lv.CallJsFunction path, jsonArgs
Registeredsupported Reg-Freeno direct equivalent
VBA
m_lv.CallJsFunction "window.myChart.update", "[1, 2, 3]"
m_lv.CallJsFunction "updateStatus", "[""Hello from VBA""]"
VBA
' Use ExecuteScriptAsync with manual call
pool.ExecuteScriptAsync idx, "updateStatus('Hello from VBA');"

Gotchas

  • The source documents no direct Reg-Free equivalent for CallJsFunction; the Reg-Free workaround shown in the source is to build the call manually with ExecuteScriptAsync, which is not a real equivalent.
  • The arguments parameter is a JSON array as a string, so string arguments need their own embedded quotes.
  • In VBA a literal double-quote inside a string is written as two double-quotes, so the VBA literal "[""Hello from VBA""]" evaluates at runtime to the JSON text ["Hello from VBA"] — a one-element array containing the string Hello from VBA.
  • The same quote-doubling rule applies to SetJsVariable.

See alsoSetJsVariable, ExecuteScriptAsync

SetJsVariableScript Execution

Set a JavaScript variable to a JSON-encoded value.

Signaturem_lv.SetJsVariable path, jsonValue
Registeredsupported Reg-Freeno direct equivalent
VBA
m_lv.SetJsVariable "window.userName", """Alice"""
m_lv.SetJsVariable "window.config", "{""debug"":true,""timeout"":5000}"
VBA
pool.ExecuteScriptAsync idx, "window.userName = 'Alice';"

Gotchas

  • The source documents no direct Reg-Free equivalent for SetJsVariable; the Reg-Free workaround shown in the source is to assign the variable manually with ExecuteScriptAsync, which is not a real equivalent.
  • The VBA literal """Alice""" evaluates at runtime to the 7-character JSON text "Alice" (a quoted JSON string — the doubled quotes collapse down to the single pair that wraps the value).
  • The VBA literal for the config object unescapes to {"debug":true,"timeout":5000}, a JSON object.
  • Same quote-doubling rule as CallJsFunction.

See alsoCallJsFunction, ExecuteScriptAsync

AddScriptToExecuteOnDocumentCreatedScript Execution

Register a script that runs automatically on every new page load. Returns a scriptId for removal.

Registered. Register document scripts before the browser exists, in Form_Load / UserForm_Initialize. There the call is queued, and the script is registered before WebViewReady fires and before the first Navigate, so it also runs on the first page. A queued call returns an empty scriptId, so there is no id to pass to RemoveScriptToExecuteOnDocumentCreated.

Once the browser exists, the call waits (up to 5 s) for WebView2 to confirm and returns the id. That works from ordinary code and from notification events, and affects later navigations only. Inside WebViewReady, other inline events and host-object methods it fails at once with &H80040203 and registers nothing.

Reg-Free. Call pool.AddScriptToExecuteOnDocumentCreated idx, script inside OnBrowserReady, before pool.Navigate. The ready callback runs from the message loop, so the call completes there.

SignaturescriptId = m_lv.AddScriptToExecuteOnDocumentCreated(script)
Registeredsupported Reg-Freesupported
VBA
Dim scriptId As String
scriptId = m_lv.AddScriptToExecuteOnDocumentCreated( _
    "window._appReady = true; console.log('LiteView2 injected');")
Debug.Print "Script ID: " & scriptId
VBA
Dim scriptId As String
scriptId = pool.AddScriptToExecuteOnDocumentCreated(idx, _
    "window._appReady = true; console.log('LiteView2 injected');")

See alsoRemoveScriptToExecuteOnDocumentCreated

RemoveScriptToExecuteOnDocumentCreatedScript Execution

Remove a previously registered auto-execute script (by the scriptId returned from AddScriptToExecuteOnDocumentCreated).

Signaturem_lv.RemoveScriptToExecuteOnDocumentCreated scriptId
Registeredsupported Reg-Freesupported
VBA
m_lv.RemoveScriptToExecuteOnDocumentCreated scriptId
VBA
pool.RemoveScriptToExecuteOnDocumentCreated idx, scriptId

See alsoAddScriptToExecuteOnDocumentCreated

IsScriptEnabled / GetScriptEnabled / SetScriptEnabled (Property)Script Execution

Get or set whether JavaScript is enabled.

Type: Boolean. Read/write.

SignatureIsScriptEnabled As Boolean · GetScriptEnabled(idx) As Boolean / SetScriptEnabled idx, value
Registeredsupported Reg-Freedocumented two ways
VBA
Debug.Print "JS enabled: " & m_lv.IsScriptEnabled   ' Get
m_lv.IsScriptEnabled = False                         ' Disable JS
VBA
Dim result As Boolean
result = pool.GetScriptEnabled(idx)
Debug.Print "JS enabled: " & result

pool.SetScriptEnabled idx, False

Gotchas

  • Registered exposes a single read/write property, IsScriptEnabled.
  • Reg-Free exposes the same setting as a separate getter/setter pair, GetScriptEnabled / SetScriptEnabled, rather than one R/W property.
  • Each of GetScriptEnabled and SetScriptEnabled is independently confirmed "Reg-Free Only" in the auto-synced reference, which also types the getter's return as Boolean.

Host Objects and the VBA to JavaScript Bridge

AddHostObjectToScriptHost Objects and the VBA to JavaScript Bridge

Expose a VBA COM object to JavaScript.

Signaturem_lv.AddHostObjectToScript "vba", helper
Registeredsupported Reg-Freesupported

Registered:

VBA
m_lv.AreHostObjectsAllowed = True
Dim helper As New clsJsBridge
m_lv.AddHostObjectToScript "vba", helper

JavaScript side (either mode):

JavaScript
const vba = chrome.webview.hostObjects.vba;
const result = await vba.GetCustomerName(123);

Reg-Free:

VBA
pool.SetAreHostObjectsAllowed idx, True
Dim helper As New clsJsBridge
pool.AddHostObjectToScript idx, "vba", helper

RemoveHostObjectFromScript / RemoveHostObjectToScriptHost Objects and the VBA to JavaScript Bridge

Remove a previously exposed host object.

Signaturem_lv.RemoveHostObjectFromScript "vba"
Registereddocumented two ways Reg-Freedocumented two ways

As RemoveHostObjectFromScript (Cookbook usage entry):

Registered:

VBA
m_lv.RemoveHostObjectFromScript "vba"

Reg-Free:

VBA
pool.RemoveHostObjectFromScript idx, "vba"

As RemoveHostObjectToScript (auto-synced-from-IDL entry):

Registered:

VBA
m_lv.RemoveHostObjectToScript name

Reg-Free:

VBA
pool.RemoveHostObjectToScript browserIndex, name

Gotchas

  • The primary Cookbook entry names this member RemoveHostObjectFromScript.
  • A separate, auto-synced-from-IDL entry elsewhere in the same document names it RemoveHostObjectToScript (same one-line description — "Remove host object from script" — same parameter shape, same mode availability).
  • The source does not state that both names exist as aliases; nothing reconciles the discrepancy.
  • Verify the actual exported member name against the type library / IntelliSense before shipping code, and prefer whichever name your IDE's autocomplete confirms.

AreHostObjectsAllowedHost Objects and the VBA to JavaScript Bridge

Enable/disable host objects.

Type: Boolean. R/W.

Signaturem_lv.AreHostObjectsAllowed = True
Registeredsupported Reg-Freesupported

Registered — true property, get and set:

VBA
m_lv.AreHostObjectsAllowed = True

Reg-Free — exposed as two explicit accessor methods, not a property, since the pool object is indexed by browser:

VBA
pool.SetAreHostObjectsAllowed idx, True
Debug.Print pool.GetAreHostObjectsAllowed(idx)

Gotchas

  • The source shows only the write form for Registered mode; the property is documented as R/W, so a get is presumed but not itself illustrated in the source.
  • Reg-Free mode does not expose this as a true property — it is split into two explicit accessor methods, GetAreHostObjectsAllowed and SetAreHostObjectsAllowed, because the pool object is indexed by browser.

See alsoGetAreHostObjectsAllowed, SetAreHostObjectsAllowed

GetAreHostObjectsAllowedHost Objects and the VBA to JavaScript Bridge

Get whether host objects are allowed in script.

Signatureresult = pool.GetAreHostObjectsAllowed(browserIndex)
Registerednot available Reg-Freesupported
VBA
Dim result As Boolean
result = pool.GetAreHostObjectsAllowed(browserIndex)

See alsoAreHostObjectsAllowed, SetAreHostObjectsAllowed

SetAreHostObjectsAllowedHost Objects and the VBA to JavaScript Bridge

Set whether host objects are allowed in script.

Signaturepool.SetAreHostObjectsAllowed browserIndex, allowed
Registerednot available Reg-Freesupported
VBA
pool.SetAreHostObjectsAllowed browserIndex, allowed

See alsoAreHostObjectsAllowed, GetAreHostObjectsAllowed

Web Messaging

PostWebMessageAsJsonWeb Messaging

Send a JSON message from VBA to JavaScript.

SignaturePostWebMessageAsJson(json As String)
Registeredsupported Reg-Freesupported
VBA
m_lv.PostWebMessageAsJson "{""type"":""update"",""value"":42}"
JavaScript
chrome.webview.addEventListener('message', function(event) {
    var data = event.data;  // {type: "update", value: 42}
    document.getElementById('divStatus').textContent = JSON.stringify(data);
});
VBA
pool.PostWebMessageAsJson idx, "{""type"":""update"",""value"":42}"

PostWebMessageAsStringWeb Messaging

Send a plain string message from VBA to JavaScript.

SignaturePostWebMessageAsString(message As String)
Registeredsupported Reg-Freesupported
VBA
m_lv.PostWebMessageAsString "Hello from VBA!"
JavaScript
chrome.webview.addEventListener('message', function(event) {
    console.log(event.data);  // "Hello from VBA!"
});
VBA
pool.PostWebMessageAsString idx, "Hello from VBA!"

SetWebMessageCallbackWeb Messaging

Register a VBA macro to receive messages sent from JavaScript.

SignatureSetWebMessageCallback(context As Object, procName As String)
Registerednot applicable Reg-Freesupported
VBA
' In Form_Load:
pool.SetWebMessageCallback idx, Application, "CB_frmMyForm"

' In modLV2Callbacks.bas:
Public Sub CB_frmMyForm(ByVal message As String, Optional ByVal source As String = "")
    If IsFormLoaded("frmMyForm") Then Forms("frmMyForm").HandleMessage message
End Sub

' In the form module:
Public Sub HandleMessage(ByVal message As String)
    If InStr(message, """action"":""save""") > 0 Then
        ' handle save action
    End If
End Sub

Gotchas

  • Reg-Free only — in Registered mode this callback is not needed; use the WebMessageReceived event instead.

See alsoWebMessageReceived

ClearWebMessageCallbackWeb Messaging

Clear the callback macro registered via SetWebMessageCallback.

SignatureClearWebMessageCallback()
Registeredsupported Reg-Freesupported
VBA
m_lv.ClearWebMessageCallback
VBA
pool.ClearWebMessageCallback idx

See alsoSetWebMessageCallback

EnableLvFacadeWeb Messaging

Inject the window.lv global JavaScript facade into every page loaded afterwards. Call it in Form_Load (queued until the browser is ready, so it covers the first page) or later from ordinary code. Inside WebViewReady and other inline events it fails at once with &H80040203. EnableLvFacade False only clears IsLvFacadeEnabled: the facade script stays registered and is still injected into later pages.

Provides lv.call(), lv.on(), lv.send(), and lv.bind().

SignatureEnableLvFacade(enable As Boolean)
Registeredsupported Reg-Freenot available
VBA
m_lv.EnableLvFacade True
' JavaScript can now use:
' lv.send({action: "save", data: {...}})
' lv.on("dataReady", function(data) { ... })
VBA
' Not available in pool - use PostWebMessageAsJson/ExecuteScript directly

Gotchas

  • Registered only — not available in Reg-Free/pool mode; use PostWebMessageAsJson/ExecuteScript directly instead.

See alsoPostWebMessageAsJson, ExecuteScript

IsLvFacadeEnabledWeb Messaging

Check whether the window.lv facade is active. Type: Boolean. Read-only.

SignatureIsLvFacadeEnabled As Boolean ' Read-only
Registeredsupported Reg-Freenot available
VBA
Debug.Print "LV Facade enabled: " & m_lv.IsLvFacadeEnabled

See alsoEnableLvFacade

IsWebMessageEnabledWeb Messaging

Get or set whether web messaging is enabled. Type: Boolean. Read/write.

Exposed differently per mode: a single R/W property in Registered mode, and a pair of separate get/set methods in Reg-Free mode.

SignatureIsWebMessageEnabled As Boolean ' Read/write
Registeredsupported Reg-Freedocumented two ways
VBA
Debug.Print "Web messaging: " & m_lv.IsWebMessageEnabled   ' Get
m_lv.IsWebMessageEnabled = True                              ' Enable
VBA
Debug.Print "Web messaging: " & pool.GetWebMessageEnabled(idx)
pool.SetWebMessageEnabled idx, True

Gotchas

  • The Reg-Free get/set pair is separately documented in the auto-synced API reference as two distinct methods, each tagged Mode: Reg-Free Only: GetWebMessageEnabled — "Get web message enabled." — and SetWebMessageEnabled — "Set web message enabled."
  • These are the same two calls shown above for Reg-Free mode, not additional members.
VBA
Dim result As Boolean
result = pool.GetWebMessageEnabled(idx)
VBA
pool.SetWebMessageEnabled idx, enabled

DOM Access and Manipulation

All code examples below reference elements in cookbook_test.html. Every member in this category is available in both Registered Mode and Reg-Free Mode; no member here is ILV2Json-standalone. Registered Mode calls the member directly on the control instance (m_lv); Reg-Free Mode calls it on the pool object (pool), passing the browser index (idx) as the first argument.

GetElementValueById / SetElementValueByIdDOM Access and Manipulation

Get or set the value of an input element by its ID.

Signaturem_lv.GetElementValueById(id) / m_lv.SetElementValueById id, value
Registeredsupported Reg-Freesupported
VBA
Dim name As String
name = m_lv.GetElementValueById("txtName")
Debug.Print "Name: " & name  ' "John Doe"

m_lv.SetElementValueById "txtName", "Jane Smith"
m_lv.SetElementValueById "txtEmail", "jane@example.com"
VBA
Dim name As String
name = pool.GetElementValueById(idx, "txtName")
Debug.Print "Name: " & name

pool.SetElementValueById idx, "txtName", "Jane Smith"
pool.SetElementValueById idx, "txtEmail", "jane@example.com"

GetElementValueByName / SetElementValueByNameDOM Access and Manipulation

Get or set an element's value by its name attribute (as opposed to its ID).

Signaturem_lv.GetElementValueByName(name) / m_lv.SetElementValueByName name, value
Registeredsupported Reg-Freesupported
VBA
Dim email As String
email = m_lv.GetElementValueByName("userEmail")
Debug.Print "Email: " & email  ' "john@example.com"

m_lv.SetElementValueByName "userEmail", "new@example.com"
VBA
Dim email As String
email = pool.GetElementValueByName(idx, "userEmail")

pool.SetElementValueByName idx, "userEmail", "new@example.com"

ClickElementByIdDOM Access and Manipulation

Click an element by its ID.

Signaturem_lv.ClickElementById id
Registeredsupported Reg-Freesupported
VBA
m_lv.ClickElementById "btnSubmit"
VBA
pool.ClickElementById idx, "btnSubmit"

ClickElementByNameDOM Access and Manipulation

Click an element by its name attribute.

Signaturem_lv.ClickElementByName name
Registeredsupported Reg-Freesupported
VBA
m_lv.ClickElementByName "agree"
VBA
pool.ClickElementByName idx, "agree"

ClickElementBySelectorDOM Access and Manipulation

Click an element identified by a CSS selector.

Signaturem_lv.ClickElementBySelector selector
Registeredsupported Reg-Freesupported
VBA
m_lv.ClickElementBySelector "#btnSubmit"
m_lv.ClickElementBySelector "button.primary"
m_lv.ClickElementBySelector "form#frmContact button[type='submit']"
VBA
pool.ClickElementBySelector idx, "#btnSubmit"

GetInnerHtmlById / SetInnerHtmlByIdDOM Access and Manipulation

Get or set the innerHTML of an element by ID.

Signaturem_lv.GetInnerHtmlById(id) / m_lv.SetInnerHtmlById id, html
Registeredsupported Reg-Freesupported
VBA
Dim html As String
html = m_lv.GetInnerHtmlById("divResults")
Debug.Print "Inner HTML: " & html  ' "Results will appear here"

m_lv.SetInnerHtmlById "divResults", "<p>Found <b>42</b> items</p>"
VBA
Dim html As String
html = pool.GetInnerHtmlById(idx, "divResults")

pool.SetInnerHtmlById idx, "divResults", "<p>Found <b>42</b> items</p>"

GetOuterHtmlById / SetOuterHtmlByIdDOM Access and Manipulation

Get the outerHTML of an element by ID, or replace an element entirely (including its own tag) by ID.

Signaturem_lv.GetOuterHtmlById(id) / m_lv.SetOuterHtmlById id, html
Registeredsupported Reg-Freesupported
VBA
Dim outer As String
outer = m_lv.GetOuterHtmlById("pageTitle")
Debug.Print outer  ' "<h2 id=""pageTitle"">Cookbook Test Page</h2>"

m_lv.SetOuterHtmlById "divResults", "<div id=""divResults""><b>Replaced!</b></div>"
VBA
Dim outer As String
outer = pool.GetOuterHtmlById(idx, "pageTitle")

pool.SetOuterHtmlById idx, "divResults", "<div id=""divResults""><b>Replaced!</b></div>"

GetOuterHtmlByName / SetOuterHtmlByNameDOM Access and Manipulation

Get or set the outerHTML of the first element matching a given name attribute.

Signaturem_lv.GetOuterHtmlByName(name) / m_lv.SetOuterHtmlByName name, html
Registeredsupported Reg-Freesupported
VBA
Dim html As String
html = m_lv.GetOuterHtmlByName("userName")
Debug.Print html

m_lv.SetOuterHtmlByName "userName", "<input type=""text"" name=""userName"" value=""New"">"
VBA
Dim html As String
html = pool.GetOuterHtmlByName(idx, "userName")

pool.SetOuterHtmlByName idx, "userName", _
    "<input type=""text"" name=""userName"" value=""New"">"

GetElementTextById / SetElementTextByIdDOM Access and Manipulation

Get or set the text content (not HTML) of an element by ID.

Signaturem_lv.GetElementTextById(id) / m_lv.SetElementTextById id, text
Registeredsupported Reg-Freesupported
VBA
Dim txt As String
txt = m_lv.GetElementTextById("divStatus")
Debug.Print "Status: " & txt  ' "Status: ready"

m_lv.SetElementTextById "divStatus", "Status: processing..."
VBA
Dim txt As String
txt = pool.GetElementTextById(idx, "divStatus")

pool.SetElementTextById idx, "divStatus", "Status: processing..."

GetElementAttributeById / SetElementAttributeById / RemoveElementAttributeByIdDOM Access and Manipulation

Get, set, or remove an arbitrary attribute value on an element by ID.

Signaturem_lv.GetElementAttributeById(id, name) / m_lv.SetElementAttributeById id, name, value / m_lv.RemoveElementAttributeById id, name
Registeredsupported Reg-Freesupported
VBA
Dim role As String
role = m_lv.GetElementAttributeById("txtName", "data-role")
Debug.Print "Role: " & role  ' "primary"

m_lv.SetElementAttributeById "txtName", "placeholder", "Enter your name"
m_lv.SetElementAttributeById "txtName", "data-role", "secondary"

m_lv.RemoveElementAttributeById "txtName", "data-role"
VBA
Dim role As String
role = pool.GetElementAttributeById(idx, "txtName", "data-role")

pool.SetElementAttributeById idx, "txtName", "placeholder", "Enter your name"

pool.RemoveElementAttributeById idx, "txtName", "data-role"

GetPageHtmlDOM Access and Manipulation

Get the complete HTML of the current page.

Signaturem_lv.GetPageHtml As String
Registeredsupported Reg-Freesupported
VBA
Dim fullHtml As String
fullHtml = m_lv.GetPageHtml
Debug.Print "HTML length: " & Len(fullHtml)
VBA
Dim fullHtml As String
fullHtml = pool.GetPageHtml(idx)

GetPageTextDOM Access and Manipulation

Get the plain text content of the page (no HTML tags).

Signaturem_lv.GetPageText As String
Registeredsupported Reg-Freesupported
VBA
Dim plainText As String
plainText = m_lv.GetPageText
Debug.Print plainText
VBA
Dim plainText As String
plainText = pool.GetPageText(idx)

ElementExistsByIdDOM Access and Manipulation

Check whether an element exists, by its ID.

Returns a Boolean.

Signaturem_lv.ElementExistsById(id) As Boolean
Registeredsupported Reg-Freesupported
VBA
If m_lv.ElementExistsById("errorDiv") Then
    Debug.Print "Error div found"
End If
VBA
If pool.ElementExistsById(idx, "errorDiv") Then
    Debug.Print "Error div found"
End If

ElementExistsBySelectorDOM Access and Manipulation

Check whether an element exists, by CSS selector.

Returns a Boolean.

Signaturem_lv.ElementExistsBySelector(selector) As Boolean
Registeredsupported Reg-Freesupported
VBA
If m_lv.ElementExistsBySelector("table#tblData tr:nth-child(2)") Then
    Debug.Print "Table has at least 2 rows"
End If
VBA
If pool.ElementExistsBySelector(idx, "table#tblData tr:nth-child(2)") Then
    Debug.Print "Table has at least 2 rows"
End If

SubmitFormByIdDOM Access and Manipulation

Submit a form by its ID.

Signaturem_lv.SubmitFormById id
Registeredsupported Reg-Freesupported
VBA
m_lv.SetElementValueById "frmName", "John Doe"
m_lv.SetElementValueById "frmMsg", "Hello"
m_lv.SubmitFormById "frmContact"
VBA
pool.SetElementValueById idx, "frmName", "John Doe"
pool.SetElementValueById idx, "frmMsg", "Hello"
pool.SubmitFormById idx, "frmContact"

SetCheckboxById / GetCheckboxByIdDOM Access and Manipulation

Set or get a checkbox's checked state by element ID.

Signaturem_lv.SetCheckboxById id, checked / m_lv.GetCheckboxById(id) As Boolean
Registeredsupported Reg-Freesupported
VBA
m_lv.SetCheckboxById "chkAgree", True
m_lv.SetCheckboxById "chkNewsletter", False

If m_lv.GetCheckboxById("chkAgree") Then
    Debug.Print "User agreed"
End If
VBA
pool.SetCheckboxById idx, "chkAgree", True
pool.SetCheckboxById idx, "chkNewsletter", False

If pool.GetCheckboxById(idx, "chkAgree") Then
    Debug.Print "User agreed"
End If

SelectOptionById / GetSelectedOptionByIdDOM Access and Manipulation

Select a <select> dropdown option by element ID and option value, or read back the currently selected option's value.

Signaturem_lv.SelectOptionById id, value / m_lv.GetSelectedOptionById(id) As String
Registeredsupported Reg-Freesupported
VBA
m_lv.SelectOptionById "ddlCountry", "DE"  ' Select Germany

Dim country As String
country = m_lv.GetSelectedOptionById("ddlCountry")
Debug.Print "Selected country: " & country  ' "US"
VBA
pool.SelectOptionById idx, "ddlCountry", "DE"

Dim country As String
country = pool.GetSelectedOptionById(idx, "ddlCountry")

FocusElementByIdDOM Access and Manipulation

Set keyboard focus to an element by its ID.

Signaturem_lv.FocusElementById id
Registeredsupported Reg-Freesupported
VBA
m_lv.FocusElementById "txtEmail"
VBA
pool.FocusElementById idx, "txtEmail"

ScrollToElementByIdDOM Access and Manipulation

Scroll an element into view by its ID.

Signaturem_lv.ScrollToElementById id
Registeredsupported Reg-Freesupported
VBA
m_lv.ScrollToElementById "scrollTarget"
VBA
pool.ScrollToElementById idx, "scrollTarget"

Data Bridge

PushRecordsetData Bridge

Serialize a DAO or ADO recordset to JSON and call a JavaScript function with the data.

Signaturem_lv.PushRecordset rs, "onSalesData"
Registeredsupported Reg-Freesupported
VBA
Dim rs As DAO.Recordset
Set rs = CurrentDb.OpenRecordset( _
    "SELECT Year(SaleDate) AS Yr, Month(SaleDate) AS Mo, " & _
    "       Sum(Quantity * UnitPrice) AS Total " & _
    "FROM tblSales " & _
    "GROUP BY Year(SaleDate), Month(SaleDate)", dbOpenSnapshot)
rs.MoveLast
rs.MoveFirst
m_lv.PushRecordset rs, "onSalesData"
rs.Close
JavaScript
function onSalesData(rows) {
    // rows = [{Yr:2024, Mo:1, Total:15234.50}, ...]
    rows.forEach(r => console.log(r.Yr + "-" + r.Mo + ": $" + r.Total));
}
VBA
pool.PushRecordset idx, rs, "onSalesData"

Gotchas

  • Use dbOpenSnapshot for GROUP BY/JOIN queries.
  • Always call rs.MoveLast : rs.MoveFirst before PushRecordset.
  • Max 100,000 rows per push.

BuildJsonData Bridge

Convert any VBA data (string, number, array, etc.) to a valid JSON string.

Works without WebView2.

Signaturejson = m_lv.BuildJson(value)
Registeredsupported Reg-Freesupported
VBA
Dim json As String
json = m_lv.BuildJson("Hello World")       ' Returns: "Hello World"
json = m_lv.BuildJson(42)                   ' Returns: 42
json = m_lv.BuildJson(Array(1, 2, 3))       ' Returns: [1,2,3]
Debug.Print json
VBA
Dim json As String
json = pool.BuildJson(idx, Array("a", "b", "c"))

FireJsEventData Bridge

Fire a CustomEvent in the page document.

JS can listen with addEventListener or window.lv.on().

Signaturem_lv.FireJsEvent "eventName", "jsonDetail"
Registeredsupported Reg-Freeno direct equivalent
VBA
m_lv.FireJsEvent "dataReady", "{""count"":42,""source"":""VBA""}"
JavaScript
document.addEventListener('dataReady', function(e) {
    console.log(e.detail);  // {count: 42, source: "VBA"}
});
VBA
' Use ExecuteScriptAsync to dispatch the event manually
pool.ExecuteScriptAsync idx, _
    "document.dispatchEvent(new CustomEvent('dataReady'," & _
    "{detail:{count:42,source:'VBA'}}));"

Gotchas

  • No FireJsEvent method exists on the pool object in Reg-Free mode.
  • The Reg-Free workaround dispatches the event manually via ExecuteScriptAsync instead of calling FireJsEvent directly.

See alsoExecuteScriptAsync

Two-Way Script Bridge

Bind an alias to a JavaScript object once, then read/write its properties and call its methods from VBA as if it were a native form control. This is the typed, two-way successor to hand-built ExecuteScript strings: instead of concatenating JavaScript by hand, you write m_lv.SetScriptProperty "page", "Title", "Customers" and total = m_lv.CallScriptSync("page", "computeTotal", 2, 3).

All members below assume the page exposes a JavaScript object, e.g. window.PageController:

HTML
<script>
  window.PageController = {
    Title: "Untitled",
    computeTotal: function (a, b) { return (a || 0) + (b || 0); },
    showToast:    function (msg)  { document.title = msg; }
  };
</script>

Bind once, after the page that defines the object has loaded: in NavigationCompleted (Registered), or later from ordinary code. A bind without LV2_BIND_VALIDATE also works in WebViewReady / OnBrowserReady and is resolved lazily. Inside WebViewReady, other inline events and host-object methods, a validating bind fails at once with &H80040203 and changes no binding. Then use the members below to drive it.

Mode availability: every member in this category is available in both Registered and Reg-Free mode. There is no standalone-ILV2Json form.

BindScriptObjectTwo-Way Script Bridge

Bind an alias to a JavaScript object expression.

Every other bridge call refers to the object by this alias. An optional flag (3rd argument — see LV2_BIND_FLAGS below) controls validation and lifetime; combine flags with +.

Signaturem_lv.BindScriptObject alias, jsExpression [, flags]
Registeredsupported Reg-Freesupported
VBA
m_lv.BindScriptObject "page", "window.PageController"

' with an optional flag (validate immediately; error if not present):
m_lv.BindScriptObject "page", "window.PageController", 1
VBA
pool.BindScriptObject idx, "page", "window.PageController"

See alsoLV2_BIND_FLAGS

UnbindScriptObjectTwo-Way Script Bridge

Release a binding.

Idempotent — unbinding an alias that isn't bound simply returns success.

Signaturem_lv.UnbindScriptObject alias
Registeredsupported Reg-Freesupported
VBA
m_lv.UnbindScriptObject "page"
VBA
pool.UnbindScriptObject idx, "page"

CallScriptTwo-Way Script Bridge

Call a method on the bound object, fire-and-forget.

Returns immediately without waiting for a result.

Signaturem_lv.CallScript alias, methodName [, arg1, arg2, ...]
Registeredsupported Reg-Freesupported
VBA
m_lv.CallScript "page", "showToast", "Saved!"
VBA
pool.CallScript idx, "page", "showToast", "Saved!"

Gotchas

  • JavaScript exceptions thrown during a fire-and-forget call are not reported back to VBA — use CallScriptSync if you need to detect failures.
  • Up to 8 arguments are supported; trailing omitted arguments are ignored.

See alsoCallScriptSync

CallScriptSyncTwo-Way Script Bridge

Call a method and block until it returns, delivering the result as a typed Variant (number, string, boolean, date, array, …).

Signatureresult = m_lv.CallScriptSync(alias, methodName [, arg1, arg2, ...])
Registeredsupported Reg-Freesupported
VBA
Dim total As Variant
total = m_lv.CallScriptSync("page", "computeTotal", 2, 3)
Debug.Print total          ' 5  (a real number, not a string)
VBA
Dim total As Variant
total = pool.CallScriptSync(idx, "page", "computeTotal", 2, 3)

Gotchas

  • If the JavaScript method returns a Promise, the call returns the error LV2_BRIDGE_PROMISE_RETURNED rather than blocking — use a synchronous method with CallScriptSync.

See alsoLV2_BRIDGE_ERR

GetScriptPropertyTwo-Way Script Bridge

Read a property of the bound object as a typed Variant.

Signaturevalue = m_lv.GetScriptProperty(alias, propertyName)
Registeredsupported Reg-Freesupported
VBA
Dim caption As Variant
caption = m_lv.GetScriptProperty("page", "Title")
VBA
Dim caption As Variant
caption = pool.GetScriptProperty(idx, "page", "Title")

Gotchas

  • Reading a property whose value is a function returns the error LV2_BRIDGE_PROPERTY_IS_FUNCTION — useful as a "does this method exist?" probe.

See alsoLV2_BRIDGE_ERR

SetScriptPropertyTwo-Way Script Bridge

Write a property of the bound object.

Signaturem_lv.SetScriptProperty alias, propertyName, value
Registeredsupported Reg-Freesupported
VBA
m_lv.SetScriptProperty "page", "Title", "Customers"
VBA
pool.SetScriptProperty idx, "page", "Title", "Customers"

Gotchas

  • Success does not guarantee the value stuck — assigning to a read-only JavaScript property is silently ignored by the page. If it matters, read it back with GetScriptProperty to confirm.

See alsoGetScriptProperty

GetLastBridgeErrorTwo-Way Script Bridge

Retrieve the last bridge error for this browser: a numeric code (an HRESULT) and a message, returned via two ByRef output arguments.

The slot is overwritten on each error and is never auto-cleared.

Signaturem_lv.GetLastBridgeError code, msg
Registeredsupported Reg-Freesupported
VBA
On Error Resume Next
Dim v As Variant
v = m_lv.CallScriptSync("page", "noSuchMethod")
If Err.Number <> 0 Then
    Dim code As Long, msg As String
    m_lv.GetLastBridgeError code, msg
    Debug.Print Hex(code) & " - " & msg     ' 80040503 - ...
End If
On Error GoTo 0
VBA
Dim code As Long, msg As String
pool.GetLastBridgeError idx, code, msg

See alsoLV2_BRIDGE_ERR

LV2_BIND_FLAGSTwo-Way Script Bridge

Pass as the optional last argument of BindScriptObject (combine with +).

SignatureLV2_BIND_FLAGS As Long ' bit flags, combine with +
FlagValueMeaning
(none)0Default — resolve lazily; the first call surfaces any resolution error.
Validate1Resolve the object at bind time; return an error immediately if it's missing.
Transient2Drop the binding on the next navigation instead of re-resolving it.
RawExpression4Accept an arbitrary JavaScript expression instead of a simple object path. You accept the injection risk — use only with trusted strings.
Async8Reserved — accepted but has no effect in this release.
FailIfBound16Return an error instead of silently replacing an existing binding.
FollowResolution32Re-evaluate the expression on every call (tracks reassignment) instead of capturing the object once at bind time.

See alsoBindScriptObject

LV2_BRIDGE_ERRTwo-Way Script Bridge

Surfaced as Err.Number and via GetLastBridgeError.

SignatureLV2_BRIDGE_ERR ' HRESULT-coded constants, &H8004xxxx
ConstantHexWhen
LV2_BRIDGE_ALIAS_NOT_FOUND&H80040501Call on an alias that was never bound.
LV2_BRIDGE_OBJECT_NOT_RESOLVED&H80040502The bound expression evaluates to nothing on the page.
LV2_BRIDGE_METHOD_NOT_FOUND&H80040503No method of that name on the object.
LV2_BRIDGE_PROPERTY_NOT_FOUND&H80040504No property of that name on the object.
LV2_BRIDGE_JS_EXCEPTION&H80040505The JavaScript threw — see the message.
LV2_BRIDGE_PROMISE_RETURNED&H80040506A sync call received a Promise; use a synchronous method.
LV2_BRIDGE_TIMEOUT&H80040507The call did not complete within 30 seconds.
LV2_BRIDGE_NOT_READY&H80040508The browser isn't ready yet.
LV2_BRIDGE_INVALID_ARG&H80040509Bad alias/member name, or a value that can't be passed.
LV2_BRIDGE_INVALID_EXPRESSION&H8004050AThe bind expression isn't a safe object path (use RawExpression to override).
LV2_BRIDGE_REENTRY_BLOCKED&H8004050BToo many nested synchronous calls.
LV2_BRIDGE_ALIAS_ALREADY_BOUND&H8004050CRebind blocked because FailIfBound was set.
LV2_BRIDGE_PROPERTY_IS_FUNCTION&H8004050DGetScriptProperty target is a function.
(no constant) E_LV2_SYNC_REENTRANT&H80040203A synchronous bridge call (CallScriptSync, GetScriptProperty, SetScriptProperty, BindScriptObject with LV2_BIND_VALIDATE) was made inside an inline event or a host-object call. Nothing was sent. Use CallScript / ExecuteScriptAsync there, or call after the handler returns.

See alsoGetLastBridgeError

Combined example: a live chart driven from a queryTwo-Way Script Bridge

A worked example that chains the members above — binding an object, writing a property, calling a method fire-and-forget, and calling a method synchronously to read a result back — into one end-to-end flow that drives a chart from a query.

VBA
' 1. load a page that defines window.Dashboard, then bind it
m_lv.NavigateToStringSync DashboardHtml()      ' your page (defines window.Dashboard)
m_lv.BindScriptObject "chart", "window.Dashboard"

' 2. drive the chart from VBA
m_lv.SetScriptProperty "chart", "Title", "Sales by Category"
m_lv.CallScript "chart", "setData", Array(120, 340, 80)   ' array arrives in JS as [120,340,80]

' 3. read the user's selection back as a typed value
Dim picked As Variant
picked = m_lv.CallScriptSync("chart", "getSelectedCategory")
If Len(CStr(picked)) > 0 Then
    Me.Filter = "Category='" & picked & "'"
    Me.FilterOn = True
End If

See alsoBindScriptObject, SetScriptProperty, CallScript, CallScriptSync

JSON Helper

LiteView2 exposes JSON functionality through three distinct call surfaces:

Note

On the source's own ILV2Json code samples: every auto-generated example for the standalone object declares its object variable as Dim json As Object / Set json = CreateObject("LiteView2.Json"), and then — for methods that take the JSON text as an argument — passes that same variable name as the argument too, e.g. result = json.Append(json, path, value). Read literally this means "pass the object to itself," which is not what the argument is: it is a JSON string to operate on. This is almost certainly a naming collision in the doc generator's template (confirmed by the Merge example, which needs two JSON-string arguments and uses json1/json2 instead of reusing the object's name). To avoid repeating that ambiguity, this reference names the object variable lvj and keeps a separate json string variable for the data being operated on. The method names, parameter order, and return types below are reproduced exactly as documented.

Note

JsonGetValue and the other JSON helpers never talk to the browser. They are safe in any handler, including WebMessageReceived.

JsonGetValueJSON Helper

Extract a value from a JSON string using a path expression.

Note

WebMessageReceived is raised after WebView2's own callback has returned, so handle the message right there: JsonGetValue, ExecuteScript and PushRecordset all work inside it. Synchronous calls fail (error &H80040203) in two places only: inside inline events such as WebViewReady / NavigationStarting, and inside VBA methods the page is calling through a host object. Inside a host method, use only calls that do not wait (ExecuteScriptAsync, PostWebMessageAsJson, the JSON helpers, DAO). See Critical Safety Warnings #1.

Signatureresult = m_lv.JsonGetValue(json, path)
Registeredsupported Reg-Freesupported
VBA
Dim json As String
json = "{""name"":""John"",""age"":30,""address"":{""city"":""NYC""}}"
Debug.Print m_lv.JsonGetValue(json, "name")          ' "John"
Debug.Print m_lv.JsonGetValue(json, "age")            ' 30
Debug.Print m_lv.JsonGetValue(json, "address.city")   ' "NYC"
VBA
Debug.Print pool.JsonGetValue(idx, json, "name")

The standalone ILV2Json object exposes this as GetValue / GetValueH / GetValueHP.

VBA
Dim lvj As Object
Set lvj = CreateObject("LiteView2.Json")
Dim result As Variant
result = lvj.GetValue(json, path)          ' plain path lookup
result = lvj.GetValueH(handle, path)       ' handle = a Parse() result; "Get value from parsed JSON handle by path."
result = lvj.GetValueHP(jsonHandle, pathHandle)   ' "Maximum performance" — both JSON and path pre-parsed; see Parse/CompilePath

Gotchas

  • Per the auto-synced reference, GetValue "Returns VT_EMPTY if not found, VT_NULL for null" — this return-type distinction is documented only for the standalone form, not restated for Registered/Reg-Free JsonGetValue.

GetValuesJSON Helper

Get multiple values at once.

pathsArray is an array of BSTR paths. Returns a SAFEARRAY of VARIANTs. No Registered or Reg-Free equivalent is documented; this exists only on the standalone ILV2Json object.

Signatureresult = lvj.GetValues(json, pathsArray)
Registerednot available Reg-Freenot available
VBA
Dim lvj As Object
Set lvj = CreateObject("LiteView2.Json")
Dim result As Variant
result = lvj.GetValues(json, pathsArray)                    ' "Get multiple values at once."
result = lvj.GetValuesH(handle, pathsArray)                 ' "Get multiple values from parsed JSON handle."
result = lvj.GetValuesHP(jsonHandle, pathHandlesArray)       ' "Get multiple values using parsed JSON + compiled path handles. Fastest bulk API."

JsonGetArrayLengthJSON Helper

Get the length of a JSON array at a given path.

Signaturecount = m_lv.JsonGetArrayLength(json, path)
Registeredsupported Reg-Freesupported
VBA
Dim json As String
json = "{""items"":[10,20,30,40]}"
Dim count As Long
count = m_lv.JsonGetArrayLength(json, "items")
Debug.Print "Array has " & count & " items"  ' 4
VBA
Dim count As Long
count = pool.JsonGetArrayLength(idx, json, "items")

Gotchas

  • No standalone ILV2Json equivalent named "ArrayLength" is documented; on the standalone object, Count doubles as the array-length check ("Count array elements or object keys at path").

See also JsonCount

JsonGetArrayItemJSON Helper

Get a specific item from a JSON array by index.

Signatureitem = m_lv.JsonGetArrayItem(json, path, index)
Registeredsupported Reg-Freesupported
VBA
Dim json As String
json = "[{""name"":""Alpha""},{""name"":""Beta""}]"
Dim item As String
item = m_lv.JsonGetArrayItem(json, "", 0)
Debug.Print item  ' {"name":"Alpha"}
VBA
Dim item As String
item = pool.JsonGetArrayItem(idx, json, "", 0)

The standalone ILV2Json object exposes this as GetItem / GetItemH / GetItemHP: "Get array element as string by index. Empty string if out of range."

VBA
Dim lvj As Object
Set lvj = CreateObject("LiteView2.Json")
Dim result As String
result = lvj.GetItem(json, path, index)
result = lvj.GetItemH(handle, path, index)               ' "Get array item from parsed JSON handle."
result = lvj.GetItemHP(jsonHandle, pathHandle, index)     ' "Get array item using pre-parsed JSON handle and compiled path."

JsonGetKeysJSON Helper

Get all keys from a JSON object at a given path.

Signaturekeys = m_lv.JsonGetKeys(json, path)
Registeredsupported Reg-Freesupported
VBA
Dim json As String
json = "{""name"":""John"",""age"":30,""city"":""NYC""}"
Dim keys As String
keys = m_lv.JsonGetKeys(json, "")
Debug.Print keys  ' ["name","age","city"]
VBA
Dim keys As String
keys = pool.JsonGetKeys(idx, json, "")

The standalone ILV2Json object exposes this as GetKeys / GetKeysH: "Get all keys from object at path as JSON array string."

VBA
Dim lvj As Object
Set lvj = CreateObject("LiteView2.Json")
Dim result As String
result = lvj.GetKeys(json, path)
result = lvj.GetKeysH(handle, path)     ' "Get keys from parsed JSON handle."

Gotchas

  • Unlike Count, Exists, GetItem, and GetValue, GetKeys has no GetKeysHP (compiled-path) variant documented.

See also JsonCount, JsonExists, JsonGetArrayItem, JsonGetValue

JsonExistsJSON Helper

Check if a path exists in a JSON string.

Signaturem_lv.JsonExists(json, path)
Registeredsupported Reg-Freesupported
VBA
Dim json As String
json = "{""user"":{""name"":""Imran""}}"

If m_lv.JsonExists(json, "user.name") Then Debug.Print "Found"
If Not m_lv.JsonExists(json, "user.email") Then
    json = m_lv.JsonSetValue(json, "user.email", "imran@example.com")
End If
VBA
If pool.JsonExists(idx, json, "user.name") Then Debug.Print "Found"

The standalone ILV2Json object exposes this as Exists / ExistsH / ExistsHP: "Check if a path exists in JSON."

VBA
Dim lvj As Object
Set lvj = CreateObject("LiteView2.Json")
Dim result As Boolean
result = lvj.Exists(json, path)
result = lvj.ExistsH(handle, path)                  ' "Check path existence in parsed JSON handle."
result = lvj.ExistsHP(jsonHandle, pathHandle)        ' "Check path existence using pre-parsed JSON handle and compiled path."

See also JsonSetValue

JsonCountJSON Helper

Count the number of keys in an object or elements in an array at a path.

Signaturen = m_lv.JsonCount(json, path)
Registeredsupported Reg-Freesupported
VBA
Dim n As Long
n = m_lv.JsonCount("{""a"":1,""b"":2,""c"":3}", "")    ' 3 (object keys)
n = m_lv.JsonCount("{""items"":[10,20,30]}", "items")    ' 3 (array elements)
VBA
Dim n As Long
n = pool.JsonCount(idx, json, "items")

The standalone ILV2Json object exposes this as Count / CountH / CountHP.

VBA
Dim lvj As Object
Set lvj = CreateObject("LiteView2.Json")
Dim result As Long
result = lvj.Count(json, path)
result = lvj.CountH(handle, path)                 ' "Count from parsed JSON handle."
result = lvj.CountHP(jsonHandle, pathHandle)       ' "Count using pre-parsed JSON handle and compiled path."

Gotchas

  • The standalone Count returns -1 if the target is not a container — this behavior is documented only for the standalone form, not restated for Registered/Reg-Free JsonCount.

See also JsonGetArrayLength

JsonIsValidJSON Helper

Check if a string is valid JSON.

Signaturem_lv.JsonIsValid(json)
Registeredsupported Reg-Freesupported
VBA
Debug.Print m_lv.JsonIsValid("{""valid"":true}")   ' True
Debug.Print m_lv.JsonIsValid("{bad json}")          ' False
VBA
Debug.Print pool.JsonIsValid(idx, "{""valid"":true}")

The standalone ILV2Json object exposes this as IsValid: "Validate JSON string syntax."

VBA
Dim lvj As Object
Set lvj = CreateObject("LiteView2.Json")
Dim result As Boolean
result = lvj.IsValid(json)

Gotchas

  • No IsValidH/IsValidHP variant is documented — this is a validity check on a raw JSON string, not something meaningfully done from an already-parsed handle.

Parse / CompilePathJSON Helper

Handle-based fast access, standalone ILV2Json object only. Parse parses JSON into a DOM tree and returns a handle for fast repeated access; CompilePath pre-compiles a path for repeated use and returns a path handle.

No Registered or Reg-Free equivalent is documented. These two methods produce the handle and pathHandle values consumed by every ...H and ...HP variant documented above (GetValueH/HP, GetValuesH/HP, GetItemH/HP, GetKeysH, ExistsH/HP, CountH/HP).

Signaturehandle = lvj.Parse(json)
Registerednot available Reg-Freenot available

Parse — Parse JSON into DOM tree. Returns a handle for fast repeated access.

VBA
Dim lvj As Object
Set lvj = CreateObject("LiteView2.Json")
Dim handle As Long
handle = lvj.Parse(json)

CompilePath — Pre-compile a path for repeated use. Returns a path handle.

VBA
Dim pathHandle As Long
pathHandle = lvj.CompilePath(path)

Combined ("HP" = handle + compiled path, the documented fastest form):

VBA
Dim handle As Long, pathHandle As Long
handle = lvj.Parse(json)
pathHandle = lvj.CompilePath("user.address.city")
Dim result As Variant
result = lvj.GetValueHP(handle, pathHandle)

Gotchas

  • Call ReleaseHandle/ReleasePath when a handle is no longer needed — the source does not document automatic cleanup for these handles.

See also JsonGetValue, GetValues, JsonGetArrayItem, JsonGetKeys, JsonExists, JsonCount, ReleaseHandle

ReleaseHandle / ReleaseAll / ReleasePathJSON Helper

Release the DOM-tree and compiled-path handles returned by Parse/CompilePath.

No Registered or Reg-Free equivalent is documented — these exist only on the standalone ILV2Json object.

Signaturelvj.ReleaseHandle handle
Registerednot available Reg-Freenot available

ReleaseHandle — Release a parsed JSON handle (from Parse). Safe to call twice.

VBA
Dim lvj As Object
Set lvj = CreateObject("LiteView2.Json")
lvj.ReleaseHandle handle

ReleasePath — Release a compiled path handle (from CompilePath). Safe to call twice.

VBA
lvj.ReleasePath pathHandle

ReleaseAll — Release every JSON and path handle held by this ILV2Json instance in one call.

VBA
lvj.ReleaseAll

See also Parse

JsonCreateObjectJSON Helper

Create an empty JSON object.

Starting point for building JSON from scratch.

Signaturejson = m_lv.JsonCreateObject()
Registeredsupported Reg-Freesupported
VBA
Dim json As String
json = m_lv.JsonCreateObject()    ' Returns: {}
VBA
Dim json As String
json = pool.JsonCreateObject(idx)

The standalone ILV2Json object exposes this as CreateObject: "Create empty JSON object string."

VBA
Dim lvj As Object
Set lvj = CreateObject("LiteView2.Json")      ' <- this CreateObject is the VBA built-in, instantiating lvj
Dim result As String
result = lvj.CreateObject()                    ' <- this CreateObject is the JSON Helper method, on lvj

Gotchas

  • The standalone object's own method is literally named CreateObject, identical to the VBA built-in function used to instantiate the object in the first place. lvj.CreateObject() (called on an existing instance) invokes the JSON Helper method; the bare CreateObject("LiteView2.Json") call invokes the VBA built-in. Not a defect, but a naming collision worth being deliberate about.

JsonCreateArrayJSON Helper

Create an empty JSON array.

Signaturejson = m_lv.JsonCreateArray()
Registeredsupported Reg-Freesupported
VBA
Dim json As String
json = m_lv.JsonCreateArray()     ' Returns: []
VBA
Dim json As String
json = pool.JsonCreateArray(idx)

The standalone ILV2Json object exposes this as CreateArray: "Create empty JSON array string."

VBA
Dim lvj As Object
Set lvj = CreateObject("LiteView2.Json")
Dim result As String
result = lvj.CreateArray()

The block of members below (JsonSetValue through JsonToRowArray, plus JsonCreateObject/JsonCreateArray above) is documented in the source under the heading "JSON MUTATION (Building & Modifying)" with the following blanket statement, which applies to all of them on the Registered/Reg-Free surfaces:

Note

All JSON mutation methods are pure native C++ — no WebView2 round-trips. They accept a JSON string and return the modified JSON. On failure, the original JSON is returned unchanged.

JsonSetValue / JsonSetValue2JSON Helper

Set or create a value at a path.

Auto-creates intermediate objects and arrays as needed.

Signaturejson = m_lv.JsonSetValue(json, path, value)
Registeredsupported Reg-Freesupported
VBA
Dim json As String
json = m_lv.JsonCreateObject()

' Set simple values
json = m_lv.JsonSetValue(json, "name", "Imran")
json = m_lv.JsonSetValue(json, "age", 30)
json = m_lv.JsonSetValue(json, "active", True)

' Auto-creates nested objects
json = m_lv.JsonSetValue(json, "address.city", "London")
json = m_lv.JsonSetValue(json, "address.country", "UK")

' Update existing value
json = m_lv.JsonSetValue(json, "name", "Ali")

' Set array element (auto-creates array with null padding)
json = m_lv.JsonSetValue(json, "scores[0]", 95)
json = m_lv.JsonSetValue(json, "scores[1]", 88)

Debug.Print m_lv.JsonPrettyPrint(json)

Reg-Free uses the suffixed name JsonSetValue2 to avoid a COM name collision on the pool's dispatch interface.

VBA
json = pool.JsonSetValue2(idx, json, "name", "Imran")
json = pool.JsonSetValue2(idx, json, "address.city", "London")

The standalone ILV2Json object exposes this as SetValue: "Set or create value at path. Auto-creates intermediate paths."

VBA
Dim lvj As Object
Set lvj = CreateObject("LiteView2.Json")
Dim result As String
result = lvj.SetValue(json, path, value)

JsonRemoveKey / JsonRemoveKey2JSON Helper

Remove a key from an object or an element from an array.

Signaturejson = m_lv.JsonRemoveKey(json, path)
Registeredsupported Reg-Freesupported
VBA
Dim json As String
json = "{""name"":""Imran"",""temp"":""delete-me"",""age"":30}"

' Remove object key
json = m_lv.JsonRemoveKey(json, "temp")
Debug.Print json  ' {"name":"Imran","age":30}

' Remove array element
json = "{""items"":[""a"",""b"",""c""]}"
json = m_lv.JsonRemoveKey(json, "items[1]")
Debug.Print json  ' {"items":["a","c"]}

Reg-Free uses the suffixed name JsonRemoveKey2 to avoid a COM name collision.

VBA
json = pool.JsonRemoveKey2(idx, json, "temp")

The standalone ILV2Json object exposes this as Remove: "Remove key or array element at path."

VBA
Dim lvj As Object
Set lvj = CreateObject("LiteView2.Json")
Dim result As String
result = lvj.Remove(json, path)

Gotchas

  • The standalone method name is Remove, not RemoveKey/JsonRemoveKey.

JsonAppendJSON Helper

Append a value to the end of an array at a given path.

Creates the array if it doesn't exist.

Signaturejson = m_lv.JsonAppend(json, path, value)
Registeredsupported Reg-Freesupported
VBA
Dim json As String
json = m_lv.JsonCreateObject()

json = m_lv.JsonAppend(json, "tags", "vba")
json = m_lv.JsonAppend(json, "tags", "com")
json = m_lv.JsonAppend(json, "tags", "webview2")
Debug.Print json  ' {"tags":["vba","com","webview2"]}
VBA
json = pool.JsonAppend(idx, json, "tags", "vba")

The standalone ILV2Json object exposes this as Append: "Append value to array at path."

VBA
Dim lvj As Object
Set lvj = CreateObject("LiteView2.Json")
Dim result As String
result = lvj.Append(json, path, value)

JsonInsertJSON Helper

Insert a value at a specific array index.

Existing elements shift right.

Signaturejson = m_lv.JsonInsert(json, path, index, value)
Registeredsupported Reg-Freesupported
VBA
Dim json As String
json = "[""a"",""c"",""d""]"
json = m_lv.JsonInsert(json, "", 1, "b")
Debug.Print json  ' ["a","b","c","d"]
VBA
json = pool.JsonInsert(idx, json, "", 1, "b")

The standalone ILV2Json object exposes this as Insert: "Insert value at array index."

VBA
Dim lvj As Object
Set lvj = CreateObject("LiteView2.Json")
Dim result As String
result = lvj.Insert(json, path, index, value)

JsonMergeJSON Helper

Merge two JSON objects.

Shallow merge replaces top-level keys; deep merge recurses into nested objects.

Signaturejson = m_lv.JsonMerge(base, overlay, deep)
Registeredsupported Reg-Freesupported
VBA
Dim base As String, overlay As String, json As String
base = "{""name"":""Imran"",""address"":{""city"":""London"",""zip"":""SW1""}}"
overlay = "{""age"":30,""address"":{""city"":""Manchester""}}"

' Shallow merge — address is replaced entirely
json = m_lv.JsonMerge(base, overlay, False)
' {"name":"Imran","address":{"city":"Manchester"},"age":30}

' Deep merge — address.city updated, address.zip preserved
json = m_lv.JsonMerge(base, overlay, True)
' {"name":"Imran","address":{"city":"Manchester","zip":"SW1"},"age":30}
VBA
json = pool.JsonMerge(idx, base, overlay, True)

The standalone ILV2Json object exposes this as Merge: "Merge two JSON objects. Set deep=True for recursive merge."

VBA
Dim lvj As Object
Set lvj = CreateObject("LiteView2.Json")
Dim result As String
result = lvj.Merge(json1, json2, deep)

JsonClearJSON Helper

Empty a container at a path.

Objects become {}, arrays become [].

Signaturejson = m_lv.JsonClear(json, path)
Registeredsupported Reg-Freesupported
VBA
Dim json As String
json = "{""cache"":{""a"":1,""b"":2},""tags"":[""x"",""y""]}"
json = m_lv.JsonClear(json, "cache")   ' cache becomes {}
json = m_lv.JsonClear(json, "tags")    ' tags becomes []
VBA
json = pool.JsonClear(idx, json, "cache")

The standalone ILV2Json object exposes this as Clear: "Clear array or object at path (empty it)."

VBA
Dim lvj As Object
Set lvj = CreateObject("LiteView2.Json")
Dim result As String
result = lvj.Clear(json, path)

JsonCompact / CompactJSON Helper

Remove null entries from a JSON array at path.

Pass empty path for root array. This member is not present in the manually-curated core sections of the source — it is documented only in the auto-synced reference, both as a control/pool method (JsonCompact, tagged Mode: Both) and as a standalone-object method (Compact, tagged Mode: ILV2Json standalone object) with identical wording.

Signatureresult = ctrl.JsonCompact(jsonString, path)
Registeredsupported Reg-Freesupported
VBA
Dim result As String
result = ctrl.JsonCompact(jsonString, path)
VBA
Dim result As String
result = pool.JsonCompact(idx, jsonString, path)
VBA
Dim lvj As Object
Set lvj = CreateObject("LiteView2.Json")
Dim result As String
result = lvj.Compact(json, path)

JsonPrettyPrintJSON Helper

Format JSON with 2-space indentation for debugging.

Max 5 MB input.

Signaturem_lv.JsonPrettyPrint(json)
Registeredsupported Reg-Freesupported
VBA
Debug.Print m_lv.JsonPrettyPrint("{""name"":""Imran"",""scores"":[95,88]}")
' {
'   "name": "Imran",
'   "scores": [
'     95,
'     88
'   ]
' }
VBA
Debug.Print pool.JsonPrettyPrint(idx, json)

The standalone ILV2Json object exposes this as PrettyPrint: "Pretty-print JSON with indentation."

VBA
Dim lvj As Object
Set lvj = CreateObject("LiteView2.Json")
Dim result As String
result = lvj.PrettyPrint(json)

Gotchas

  • The 5 MB input cap is stated only for the Registered/Reg-Free form in the core source; the auto-synced standalone PrettyPrint entry does not repeat or contradict it.

JsonFlattenJSON Helper

Flatten nested JSON to a flat object with dot-notation keys.

Signatureflat = m_lv.JsonFlatten(json)
Registeredsupported Reg-Freesupported
VBA
Dim flat As String
flat = m_lv.JsonFlatten("{""user"":{""name"":""Imran"",""address"":{""city"":""London""}}}")
Debug.Print flat  ' {"user.name":"Imran","user.address.city":"London"}
VBA
Dim flat As String
flat = pool.JsonFlatten(idx, json)

The standalone ILV2Json object exposes this as Flatten: "Flatten nested JSON. E.g. {a:{b:1}} becomes {"a.b":1}."

VBA
Dim lvj As Object
Set lvj = CreateObject("LiteView2.Json")
Dim result As String
result = lvj.Flatten(json)

JsonUnflattenJSON Helper

Convert a flat dot-notation object back to nested JSON.

Signaturenested = m_lv.JsonUnflatten(flat)
Registeredsupported Reg-Freesupported
VBA
Dim nested As String
nested = m_lv.JsonUnflatten("{""user.name"":""Imran"",""user.address.city"":""London""}")
Debug.Print nested  ' {"user":{"name":"Imran","address":{"city":"London"}}}
VBA
Dim nested As String
nested = pool.JsonUnflatten(idx, flat)

The standalone ILV2Json object exposes this as Unflatten: "Unflatten dot-notation JSON back to nested structure."

VBA
Dim lvj As Object
Set lvj = CreateObject("LiteView2.Json")
Dim result As String
result = lvj.Unflatten(json)

JsonToArrayJSON Helper

Convert a JSON array to a VBA 2D array (for Excel ranges or data processing).

No header row — data starts at arr(1,1). (Contrast with JsonToRowArray, which adds a header row.)

Signaturearr = m_lv.JsonToArray(json)
Registeredsupported Reg-Freesupported
VBA
Dim json As String
json = "[{""Date"":""2024-01-01"",""Open"":100,""Close"":105}," & _
       "{""Date"":""2024-01-02"",""Open"":105,""Close"":110}]"
Dim arr As Variant
arr = m_lv.JsonToArray(json)
' arr is now a 2D array: arr(1,1)="2024-01-01", arr(1,2)=100, etc.
VBA
Dim arr As Variant
arr = pool.JsonToArray(idx, json)

The standalone ILV2Json object exposes this as ToArray: "Validate and return JSON array (enforces MaxSize limit)."

VBA
Dim lvj As Object
Set lvj = CreateObject("LiteView2.Json")
Dim result As Variant
result = lvj.ToArray(json)

Gotchas

  • The standalone ToArray description is noticeably terser than, and does not explicitly restate, the Registered/Reg-Free description ("convert a JSON array to a VBA 2D array"); it is presented here as the same-named member rather than a confirmed identical behavior, since the source does not state outright that the two are equivalent.

See also JsonToRowArray, JsonToArrayMaxSize

JsonToArrayMaxSizeJSON Helper

Max JSON size in bytes for JsonToArray and JsonToRowArray.

Type: Long. R/W. Default: 52428800 (50MB).

Signaturem_lv.JsonToArrayMaxSize [= value]
Registeredsupported Reg-Freenot available as a pool property — uses default
VBA
' Registered
Debug.Print m_lv.JsonToArrayMaxSize           ' 52428800
m_lv.JsonToArrayMaxSize = 104857600           ' Set to 100MB
VBA
' Reg-Free
' Not available as a pool property - use default

Gotchas

  • Not exposed as a Reg-Free pool property — the pool uses the default limit and there is no pool.JsonToArrayMaxSize setter documented.

See also JsonToArray, JsonToRowArray, MaxSize

MaxSizeJSON Helper

Maximum JSON size in bytes for Parse/ToArray/ToRowArray on the standalone ILV2Json object.

Default 50MB. Range: 1KB–500MB. Wider scope than JsonToArrayMaxSize: it also governs Parse, and the source states an explicit min/max range that JsonToArrayMaxSize does not.

Signaturepool.GetMaxSize browserIndex, value
Registerednot available Reg-Freedocumented two ways

Caution

This property is tagged Mode: ILV2Json (standalone object), but unlike every other ILV2Json member (which is always exercised via Dim lvj As Object: Set lvj = CreateObject("LiteView2.Json") then lvj.Method(...)), the documented Get/Set code samples use the Reg-Free pool + browser-index calling convention instead:

VBA
' As literally documented — Get:
Dim value As Long
pool.GetMaxSize browserIndex, value

' As literally documented — Set:
pool.SetMaxSize browserIndex, newValue  ' newValue As Long

The source does not explain this — it may mean the property is actually reached through the pool (and the "ILV2Json standalone" mode tag is wrong), or the code sample itself may be the error (and it should read lvj.GetMaxSize/lvj.SetMaxSize with no browser index, or a plain lvj.MaxSize property get/let). Both the tag and the sample are reproduced verbatim above; do not assume either one over the other without checking the IDL directly.

Gotchas

  • Tagged in source as standalone-only, but the only documented call samples use the Reg-Free pool + browser-index convention (pool.GetMaxSize / pool.SetMaxSize) rather than lvj.MaxSize — an unresolved contradiction; see the caution above.
  • Governs Parse, ToArray, and ToRowArray on the standalone object — wider scope than the control's JsonToArrayMaxSize, which only governs JsonToArray/JsonToRowArray and does not document a min/max range.

See also JsonToArrayMaxSize, Parse, JsonToArray, JsonToRowArray

JsonToRowArray / JsonToRowArray2JSON Helper

Convert a JSON array of objects to a 2D VBA array.

Row 1 contains column headers; subsequent rows contain typed values. Respects JsonToArrayMaxSize.

Signaturearr = m_lv.JsonToRowArray(json)
Registeredsupported Reg-Freesupported
VBA
Dim json As String
json = "[{""Name"":""Imran"",""Age"":30,""Active"":true}," & _
       "{""Name"":""Ali"",""Age"":25,""Active"":false}]"

Dim arr As Variant
arr = m_lv.JsonToRowArray(json)
' arr(1,1)="Name"  arr(1,2)="Age"  arr(1,3)="Active"   ← headers
' arr(2,1)="Imran" arr(2,2)=30     arr(2,3)=True        ← data
' arr(3,1)="Ali"   arr(3,2)=25     arr(3,3)=False

' Loop through data rows
Dim r As Long, c As Long
For r = 2 To UBound(arr, 1)
    For c = 1 To UBound(arr, 2)
        Debug.Print arr(r, c);
    Next c
    Debug.Print
Next r

Reg-Free uses the suffixed name JsonToRowArray2 to avoid a COM name collision.

VBA
Dim arr As Variant
arr = pool.JsonToRowArray2(idx, json)

The standalone ILV2Json object exposes this as ToRowArray: "Convert JSON array-of-objects to 2D SAFEARRAY. Row 1=headers, rows 2+=data."

VBA
Dim lvj As Object
Set lvj = CreateObject("LiteView2.Json")
Dim result As Variant
result = lvj.ToRowArray(json)

Type mapping, documented for JsonToRowArray/JsonToRowArray2 (not restated separately for the standalone form):

JSON TypeVBA Type
stringvbString
number (integer)vbLong
number (decimal)vbDouble
booleanvbBoolean
nullvbEmpty
object / arrayvbString (serialized JSON)

See also JsonToArray, JsonToArrayMaxSize

JsonUnwrapStringJSON Helper

If input is a JSON string literal (double-encoded), unwrap one layer and unescape.

Otherwise return unchanged. This member is not present in the manually-curated core sections; it is documented only in the auto-synced reference, tagged Mode: Both (Registered + Reg-Free), plus a standalone-object form with identical wording.

Signatureresult = ctrl.JsonUnwrapString(jsonValue)
Registeredsupported Reg-Freesupported
VBA
Dim result As String
result = ctrl.JsonUnwrapString(jsonValue)
VBA
Dim result As String
result = pool.JsonUnwrapString(idx, jsonValue)

The standalone ILV2Json object exposes this as UnwrapString.

VBA
Dim lvj As Object
Set lvj = CreateObject("LiteView2.Json")
Dim result As String
result = lvj.UnwrapString(jsonValue)

Two structural notes apply across the whole ILV2Json handle system, stated here once rather than repeated per-member:

Browser Automation

High-level automation helpers using CSS selectors (Playwright-style automation API).

WaitForElementBrowser Automation

Wait for an element matching a CSS selector to appear in the DOM.

Returns True if found, False on timeout. Polls every 50ms using ElementExistsBySelector, pumping messages between checks so the UI stays responsive.

Signaturem_lv.WaitForElement(selector As String, [timeoutMs As Long]) As Boolean
Registeredsupported Reg-Freesupported
VBA
m_lv.Navigate "https://example.com/login"

' Wait up to 10 seconds for login form
If m_lv.WaitForElement("#loginForm", 10000) Then
    Debug.Print "Form appeared!"
Else
    Debug.Print "Timed out waiting for form"
End If

' Wait for dynamic content after AJAX load
m_lv.ClickElementBySelector ".load-more-btn"
If m_lv.WaitForElement(".new-results", 5000) Then
    Debug.Print "Results loaded"
End If
VBA
If pool.WaitForElement(idx, "#dashboard", 10000) Then
    Debug.Print "Dashboard ready"
End If

Gotchas

  • If timeoutMs is 0, the SynchronousTimeOut property value is used (default 30s).
  • The UI remains responsive during the wait — messages are pumped between polls.

GetTextBySelectorBrowser Automation

Get the text content of the first element matching a CSS selector.

Signaturem_lv.GetTextBySelector(selector As String) As String
Registeredsupported Reg-Freesupported
VBA
Dim welcome As String
welcome = m_lv.GetTextBySelector(".welcome-message")
Debug.Print welcome

Dim price As String
price = m_lv.GetTextBySelector("#product-price .amount")
Debug.Print "Price: " & price
VBA
Dim txt As String
txt = pool.GetTextBySelector(idx, ".status-text")

Automation API — Complete Workflow Example

Navigate to a site, wait for dynamic content, interact, and read results (illustrates WaitForElement and GetTextBySelector combined with element-interaction methods documented elsewhere in this reference: SetElementValueById, ClickElementBySelector):

Registered:

VBA
' Navigate
m_lv.Navigate "https://example.com/login"

' Wait for login form
If m_lv.WaitForElement("#loginForm", 10000) Then
    ' Fill form
    m_lv.SetElementValueById "email", "user@example.com"
    m_lv.SetElementValueById "password", "secret123"

    ' Submit via CSS selector
    m_lv.ClickElementBySelector "#loginForm button[type='submit']"

    ' Wait for dashboard
    If m_lv.WaitForElement(".dashboard-panel", 15000) Then
        Dim msg As String
        msg = m_lv.GetTextBySelector(".welcome-message")
        Debug.Print "Logged in: " & msg
    End If
End If

Downloads

Note

Naming pattern across this category: the Registered-mode control exposes each item as a native COM property/method on m_lv. Reg-Free mode's pool object exposes the equivalent capability through explicit GetXxx/SetXxx (or bare action) methods taking idx as the first argument, since the late-bound pool interface does not carry real property accessors. Where the auto-synced IDL reference tags a property entry "Mode: Registered Only," that tag describes the COM property-accessor syntax specifically — the Reg-Free equivalent still exists, under the GetXxx/SetXxx method names documented alongside it below. This is a consistent convention, not a contradiction, and applies to every R/W property in this category.

OpenDownloadDialogDownloads

Open the download manager dialog.

Signaturem_lv.OpenDownloadDialog
Registeredsupported Reg-Freesupported
VBA
m_lv.OpenDownloadDialog
VBA
pool.OpenDownloadDialog idx

CloseDownloadDialogDownloads

Close the download manager dialog.

Signaturem_lv.CloseDownloadDialog
Registeredsupported Reg-Freesupported
VBA
m_lv.CloseDownloadDialog
VBA
pool.CloseDownloadDialog idx

IsDownloadDialogOpenDownloads

Check if the download dialog is currently open. Type: Boolean. Read-only.

Signaturem_lv.IsDownloadDialogOpen As Boolean ' Read-only
Registeredsupported Reg-Freesupported
VBA
If m_lv.IsDownloadDialogOpen Then m_lv.CloseDownloadDialog
VBA
If pool.IsDownloadDialogOpen(idx) Then pool.CloseDownloadDialog idx

PauseDownloadDownloads

Pause an active download by its download ID.

Signaturem_lv.PauseDownload downloadId
Registeredsupported Reg-Freesupported
VBA
m_lv.PauseDownload downloadId
VBA
pool.PauseDownload idx, downloadId

ResumeDownloadDownloads

Resume a paused download by ID.

Signaturem_lv.ResumeDownload downloadId
Registeredsupported Reg-Freesupported
VBA
m_lv.ResumeDownload downloadId
VBA
pool.ResumeDownload idx, downloadId

CancelDownloadDownloads

Cancel a download by ID.

Signaturem_lv.CancelDownload downloadId
Registeredsupported Reg-Freesupported
VBA
m_lv.CancelDownload downloadId
VBA
pool.CancelDownload idx, downloadId

AllowDownloadsDownloads

Get or set whether downloads are allowed. Type: Boolean. R/W.

Signaturem_lv.AllowDownloads As Boolean ' R/W
Registeredsupported Reg-Freesupported
VBA
Debug.Print m_lv.AllowDownloads
m_lv.AllowDownloads = False   ' Block all downloads
VBA
Debug.Print pool.GetAllowDownloads(idx)
pool.SetAllowDownloads idx, False

Gotchas

  • Auto-synced IDL reference confirms GetAllowDownloads (returns Boolean) and SetAllowDownloads (takes browserIndex, allowed) are both tagged Mode: Reg-Free Only — matching the base entry's naming convention, not a conflict with it.

DefaultDownloadFolderPathDownloads

Get or set the default download folder. Type: String. R/W.

Signaturem_lv.DefaultDownloadFolderPath As String ' R/W
Registeredsupported Reg-Freesupported
VBA
Debug.Print m_lv.DefaultDownloadFolderPath
m_lv.DefaultDownloadFolderPath = "C:\Downloads"
VBA
Debug.Print pool.GetDefaultDownloadFolderPath(idx)
pool.SetDefaultDownloadFolderPath idx, "C:\Downloads"

Gotchas

  • Auto-synced IDL reference confirms GetDefaultDownloadFolderPath (returns String, via browserIndex) and SetDefaultDownloadFolderPath (takes browserIndex, folderPath) are both tagged Mode: Reg-Free Only — matching the base entry.

HiddenDownloadUIDownloads

Get or set whether download UI is hidden (silent downloads). Type: Boolean. R/W.

Signaturem_lv.HiddenDownloadUI As Boolean ' R/W
Registeredsupported Reg-Freesupported
VBA
m_lv.HiddenDownloadUI = True   ' Silent downloads
VBA
Debug.Print pool.GetHiddenDownloadUI(idx)
pool.SetHiddenDownloadUI idx, True

Gotchas

  • The base Cookbook entry documents only this Set form for Registered mode; no Debug.Print/Get example is given there, even though the property is documented R/W.
  • The base entry documents only SetHiddenDownloadUI for Reg-Free. The auto-synced IDL reference adds GetHiddenDownloadUI (returns Boolean, via browserIndex), tagged Mode: Reg-Free Only — merged into the Reg-Free example above as the Get counterpart.

DefaultDownloadDialogCornerAlignmentDownloads

Download dialog corner position. Type: LV2_DOWNLOAD_DIALOG_CORNER_ALIGNMENT. R/W.

Signaturem_lv.DefaultDownloadDialogCornerAlignment As LV2_DOWNLOAD_DIALOG_CORNER_ALIGNMENT ' R/W
Registeredsupported Reg-Freesupported
VBA
m_lv.DefaultDownloadDialogCornerAlignment = 3  ' LV2_DOWNLOAD_CORNER_BOTTOM_RIGHT
VBA
pool.SetDefaultDownloadDialogCornerAlignment idx, 3
VBA
Dim result As LV2_DOWNLOAD_DIALOG_CORNER_ALIGNMENT
result = pool.GetDefaultDownloadDialogCornerAlignment(idx)

Gotchas

  • Base entry documents only the Set form for Registered mode; no Get example is given there.
  • The auto-synced IDL reference adds the Reg-Free Get counterpart shown above (GetDefaultDownloadDialogCornerAlignment), tagged Mode: Reg-Free Only.

DefaultDownloadDialogMarginX / DefaultDownloadDialogMarginYDownloads

Download dialog margin from corner, in pixels. Type: Long. R/W.

Signaturem_lv.DefaultDownloadDialogMarginX / DefaultDownloadDialogMarginY As Long ' R/W
Registeredsupported Reg-Freesupported
VBA
m_lv.DefaultDownloadDialogMarginX = 20
m_lv.DefaultDownloadDialogMarginY = 20
VBA
Dim value As Long
value = m_lv.DefaultDownloadDialogMarginX
m_lv.DefaultDownloadDialogMarginX = newValue  ' newValue As Long

value = m_lv.DefaultDownloadDialogMarginY
m_lv.DefaultDownloadDialogMarginY = newValue  ' newValue As Long
VBA
pool.SetDefaultDownloadDialogMarginX idx, 20
pool.SetDefaultDownloadDialogMarginY idx, 20
VBA
Dim result As Long
result = pool.GetDefaultDownloadDialogMarginX(idx)
result = pool.GetDefaultDownloadDialogMarginY(idx)

Gotchas

  • The auto-synced IDL reference documents DefaultDownloadDialogMarginX and DefaultDownloadDialogMarginY as separate entries, each tagged Mode: Registered Only (describing the COM property-accessor form specifically), and adds the Get direction shown above — not present in the base Registered entry.
  • The auto-synced IDL reference adds the Reg-Free Get counterparts shown above (GetDefaultDownloadDialogMarginX, GetDefaultDownloadDialogMarginY), each tagged Mode: Reg-Free Only.

Cookies and Browsing Data

ClearCacheCookies and Browsing Data

Clear the browser cache.

Signaturem_lv.ClearCache
Registeredsupported Reg-Freesupported
VBA
m_lv.ClearCache
VBA
pool.ClearCache idx

ClearCookiesCookies and Browsing Data

Clear all cookies.

Signaturem_lv.ClearCookies
Registeredsupported Reg-Freesupported
VBA
m_lv.ClearCookies
VBA
pool.ClearCookies idx

ClearBrowsingDataCookies and Browsing Data

Clear browsing data by bitmask of LiteView2BrowsingDataKinds.

Parameters: a Long bitmask combining LiteView2BrowsingDataKinds flags. The source documents these two flag combinations by example:

  • LV2_DATA_DISK_CACHE (256) + LV2_DATA_COOKIES (64) — clears cache + cookies
  • LV2_DATA_ALL_PROFILE (16384) — clears everything
Signaturem_lv.ClearBrowsingData flags
Registeredsupported Reg-Freesupported
VBA
' Clear cache + cookies
m_lv.ClearBrowsingData 256 + 64   ' LV2_DATA_DISK_CACHE + LV2_DATA_COOKIES
' Clear everything
m_lv.ClearBrowsingData 16384      ' LV2_DATA_ALL_PROFILE
VBA
pool.ClearBrowsingData idx, 256 + 64

ClearBrowsingDataInTimeRangeCookies and Browsing Data

Clear browsing data within a specific time range.

Known issue in 1.0.1.0

ClearBrowsingDataInTimeRange returns without an error but clears nothing. Use ClearBrowsingData (all time) or ClearCookies instead.

Parameters: Long bitmask of LiteView2BrowsingDataKinds, start time, end time.

Signaturem_lv.ClearBrowsingDataInTimeRange flags, startTime, endTime
Registeredsupported Reg-Freesupported
VBA
' Clear last 24 hours of cookies
m_lv.ClearBrowsingDataInTimeRange 64, Now - 1, Now
VBA
pool.ClearBrowsingDataInTimeRange idx, 64, Now - 1, Now

GetCookiesCookies and Browsing Data

Get cookies for a URL as a JSON string.

Parameters: URL (String). Returns a String containing JSON.

SignaturecookiesJson = m_lv.GetCookies(url)
Registeredsupported Reg-Freesupported
VBA
Dim cookiesJson As String
cookiesJson = m_lv.GetCookies("https://www.example.com")
Debug.Print cookiesJson
VBA
Dim cookiesJson As String
cookiesJson = pool.GetCookies(idx, "https://www.example.com")

SetCookieCookies and Browsing Data

Set a cookie.

Parameters (in order, per the documented example): name, value, domain, path — all String.

Signaturem_lv.SetCookie name, value, domain, path
Registeredsupported Reg-Freesupported
VBA
m_lv.SetCookie "sessionId", "abc123", ".example.com", "/"
VBA
pool.SetCookie idx, "sessionId", "abc123", ".example.com", "/"

ClearProfileCookiesCookies and Browsing Data

Clear all cookies for the current profile.

Signaturem_lv.ClearProfileCookies
Registeredsupported Reg-Freesupported
VBA
m_lv.ClearProfileCookies
VBA
pool.ClearProfileCookies idx

Printing, PDF and Capture

PrintPagePrinting, PDF and Capture

Print the current page to the default printer.

Signaturem_lv.PrintPage
Registeredsupported Reg-Freeno direct equivalent
VBA
m_lv.PrintPage
VBA
' Use ShowPrintDialog instead
pool.ShowPrintDialog idx

Gotchas

  • Reg-Free has no direct equivalent for PrintPage; the source explicitly says to use ShowPrintDialog instead.

See alsoShowPrintDialog

ShowPrintDialogPrinting, PDF and Capture

Show the system print dialog.

Signaturem_lv.ShowPrintDialog
Registeredsupported Reg-Freesupported
VBA
m_lv.ShowPrintDialog
VBA
pool.ShowPrintDialog idx

See alsoPrintPage

PrintToPdfPrinting, PDF and Capture

Print the current page to a PDF file.

Signaturem_lv.PrintToPdf path
Registeredsupported Reg-Freesupported
VBA
Dim path As String
path = Environ("USERPROFILE") & "\Desktop\Report_" & _
       Format(Now(), "yyyymmdd_hhnnss") & ".pdf"
m_lv.PrintToPdf path
' Fires PrintToPdfCompleted event when done
VBA
Dim path As String
path = Environ("USERPROFILE") & "\Desktop\Report.pdf"
pool.PrintToPdf idx, path

Gotchas

  • Registered mode: handle the PrintToPdfCompleted event for the success callback.
  • Reg-Free mode: PrintToPdf is fire-and-forget — check Dir(path) <> "" on next user action, or wrap in a host-object callback if you need a result signal.

See alsoPrintToPdfCompleted, HasPrintToPdf

PrintWithSettingsPrinting, PDF and Capture

Print using the current print settings (no dialog).

Signaturem_lv.PrintWithSettings
Registeredsupported Reg-Freesupported
VBA
m_lv.PrintOrientation = 1  ' Landscape
m_lv.PrintShouldPrintBackgrounds = True
m_lv.PrintWithSettings
VBA
pool.SetPrintOrientation idx, 1
pool.SetPrintShouldPrintBackgrounds idx, True
pool.PrintWithSettings idx

See alsoPrintOrientation, PrintShouldPrintBackgrounds

PrintToPdfWithSettingsPrinting, PDF and Capture

Print to PDF using the current print settings.

Signaturem_lv.PrintToPdfWithSettings path
Registeredsupported Reg-Freesupported
VBA
m_lv.PrintOrientation = 1
m_lv.PrintMarginTop = 0.25
m_lv.PrintMarginBottom = 0.25
m_lv.PrintToPdfWithSettings Environ("USERPROFILE") & "\Desktop\Report.pdf"
VBA
pool.SetPrintOrientation idx, 1
pool.SetPrintMarginTop idx, 0.25
pool.SetPrintMarginBottom idx, 0.25
pool.PrintToPdfWithSettings idx, Environ("USERPROFILE") & "\Desktop\Report.pdf"

See alsoPrintOrientation, PrintMarginTop, PrintMarginBottom, PrintToPdf

CaptureScreenshotPrinting, PDF and Capture

Capture a screenshot of the page to a PNG file.

Signaturem_lv.CaptureScreenshot path
Registeredsupported Reg-Freesupported
VBA
m_lv.CaptureScreenshot Environ("USERPROFILE") & "\Desktop\screenshot.png"
' Fires CaptureScreenshotCompleted event
VBA
pool.CaptureScreenshot idx, Environ("USERPROFILE") & "\Desktop\screenshot.png"

Gotchas

  • Registered mode: handle the CaptureScreenshotCompleted event for the success callback.
  • Reg-Free mode: check Dir(path) <> "" on next user action.

See alsoCaptureScreenshotCompleted, HasCapturePreview

ShowSaveAsDialogPrinting, PDF and Capture

Show the Save As dialog for the current page.

Signaturem_lv.ShowSaveAsDialog
Registeredsupported Reg-Freesupported
VBA
m_lv.ShowSaveAsDialog
VBA
pool.ShowSaveAsDialog idx

OpenTaskManagerWindowPrinting, PDF and Capture

Open the browser task manager window (debugging).

Signaturem_lv.OpenTaskManagerWindow
Registeredsupported Reg-Freesupported
VBA
m_lv.OpenTaskManagerWindow
VBA
pool.OpenTaskManagerWindow idx

PrintOrientation (Property)Printing, PDF and Capture

Print orientation. Type: LV2_PRINT_ORIENTATION (0 = Portrait, 1 = Landscape). Read/Write.

Signaturem_lv.PrintOrientation [= LV2_PRINT_ORIENTATION]
Registeredsupported Reg-Freesupported
VBA
Debug.Print m_lv.PrintOrientation            ' 0 (Portrait)
m_lv.PrintOrientation = 1                    ' Landscape
VBA
Dim orient As Long
pool.GetPrintOrientation idx, orient
pool.SetPrintOrientation idx, 1

Gotchas

  • Reg-Free exposes this as a getter sub taking the value ByRef, not a function return — the calling convention differs from the Registered property syntax.

PrintScaleFactor (Property)Printing, PDF and Capture

Print scale factor. Type: Double. Read/Write. Default: 1.0.

Signaturem_lv.PrintScaleFactor [= Double]
Registeredsupported Reg-Freesupported
VBA
Debug.Print m_lv.PrintScaleFactor
m_lv.PrintScaleFactor = 0.75   ' 75% scale
VBA
Dim sf As Double
pool.GetPrintScaleFactor idx, sf
pool.SetPrintScaleFactor idx, 0.75

PrintMarginTop / PrintMarginBottom / PrintMarginLeft / PrintMarginRight (Properties)Printing, PDF and Capture

Print margins in inches. Type: Double. Read/Write.

Signaturem_lv.PrintMarginTop / PrintMarginBottom / PrintMarginLeft / PrintMarginRight [= Double]
Registeredsupported Reg-Freesupported
VBA
m_lv.PrintMarginTop = 0.5
m_lv.PrintMarginBottom = 0.5
m_lv.PrintMarginLeft = 0.75
m_lv.PrintMarginRight = 0.75
Debug.Print m_lv.PrintMarginTop   ' 0.5
VBA
pool.SetPrintMarginTop idx, 0.5
pool.SetPrintMarginBottom idx, 0.5
pool.SetPrintMarginLeft idx, 0.75
pool.SetPrintMarginRight idx, 0.75

PrintPageWidth / PrintPageHeight (Properties)Printing, PDF and Capture

Print page dimensions in inches. Type: Double. Read/Write.

Signaturem_lv.PrintPageWidth / PrintPageHeight [= Double]
Registeredsupported Reg-Freesupported
VBA
m_lv.PrintPageWidth = 8.5
m_lv.PrintPageHeight = 11.0
Debug.Print m_lv.PrintPageWidth & " x " & m_lv.PrintPageHeight
VBA
pool.SetPrintPageWidth idx, 8.5
pool.SetPrintPageHeight idx, 11.0

PrintShouldPrintBackgrounds (Property)Printing, PDF and Capture

Print background graphics. Type: Boolean. Read/Write.

Signaturem_lv.PrintShouldPrintBackgrounds [= Boolean]
Registeredsupported Reg-Freesupported
VBA
m_lv.PrintShouldPrintBackgrounds = True
VBA
pool.SetPrintShouldPrintBackgrounds idx, True

PrintShouldPrintSelectionOnly (Property)Printing, PDF and Capture

Print only the current selection. Type: Boolean. Read/Write.

Signaturem_lv.PrintShouldPrintSelectionOnly [= Boolean]
Registeredsupported Reg-Freesupported
VBA
m_lv.PrintShouldPrintSelectionOnly = True
VBA
pool.SetPrintShouldPrintSelectionOnly idx, True

PrintShouldPrintHeaderAndFooter (Property)Printing, PDF and Capture

Print header and footer. Type: Boolean. Read/Write.

Signaturem_lv.PrintShouldPrintHeaderAndFooter [= Boolean]
Registeredsupported Reg-Freesupported
VBA
m_lv.PrintShouldPrintHeaderAndFooter = True
VBA
pool.SetPrintShouldPrintHeaderAndFooter idx, True

PrintHeaderTitle (Property)Printing, PDF and Capture

Custom header title for printing. Type: String. Read/Write.

Signaturem_lv.PrintHeaderTitle [= String]
Registeredsupported Reg-Freesupported
VBA
m_lv.PrintHeaderTitle = "My Report"
Debug.Print m_lv.PrintHeaderTitle
VBA
pool.SetPrintHeaderTitle idx, "My Report"

PrintFooterUri (Property)Printing, PDF and Capture

Custom footer URI for printing. Type: String. Read/Write.

Signaturem_lv.PrintFooterUri [= String]
Registeredsupported Reg-Freesupported
VBA
m_lv.PrintFooterUri = "https://myapp.com/reports"
VBA
pool.SetPrintFooterUri idx, "https://myapp.com/reports"

PrintCopies (Property)Printing, PDF and Capture

Number of copies to print. Type: Long. Read/Write.

Signaturem_lv.PrintCopies [= Long]
Registeredsupported Reg-Freesupported
VBA
m_lv.PrintCopies = 2
VBA
pool.SetPrintCopies idx, 2

PrintPagesPerSide (Property)Printing, PDF and Capture

Pages per side (N-up printing). Type: Long. Read/Write.

Signaturem_lv.PrintPagesPerSide [= Long]
Registeredsupported Reg-Freesupported
VBA
m_lv.PrintPagesPerSide = 2
VBA
pool.SetPrintPagesPerSide idx, 2

PrintPageRanges (Property)Printing, PDF and Capture

Page ranges for printing. Type: String. Read/Write. Example: "1-3,5,7".

Signaturem_lv.PrintPageRanges [= String]
Registeredsupported Reg-Freesupported
VBA
m_lv.PrintPageRanges = "1-3,5"
Debug.Print m_lv.PrintPageRanges
VBA
pool.SetPrintPageRanges idx, "1-3,5"

HasPrintToPdf (Property)Printing, PDF and Capture

Check if PrintToPdf is supported by the runtime. Type: Boolean. Read-only.

Signaturem_lv.HasPrintToPdf
Registeredsupported Reg-Freesupported
VBA
If m_lv.HasPrintToPdf Then
    m_lv.PrintToPdf "C:\output.pdf"
End If
VBA
If pool.HasPrintToPdf(idx) Then
    pool.PrintToPdf idx, "C:\output.pdf"
End If

Gotchas

  • Reg-Free calls this as a function that takes idx and returns the Boolean (pool.HasPrintToPdf(idx)), rather than a plain property read.

See alsoPrintToPdf

HasCapturePreview (Property)Printing, PDF and Capture

Check if CapturePreview (screenshot) is supported. Type: Boolean. Read-only.

Signaturem_lv.HasCapturePreview
Registeredsupported Reg-Freesupported
VBA
Debug.Print "Screenshot support: " & m_lv.HasCapturePreview
VBA
Debug.Print "Screenshot support: " & pool.HasCapturePreview(idx)

See alsoCaptureScreenshot

Authentication and Web Resources

Custom Web Resource Requests

These five members let you build and issue HTTP requests with a custom method, headers, and body, and let you supply a synthetic response for a request the control intercepts. CreateWebResourceRequest and CreateWebResourceResponse return an opaque Long handle; that handle is what NavigateWithCustomRequest and NavigateWithWebResourceRequestSync consume.

Note on parameter order: NavigateWithWebResourceRequest takes arguments in the order (url, method, postData, headers), while CreateWebResourceRequest takes them in the order (method, url, headers, postData). This is not a typo in this reference — the two argument orders are documented differently in the source and must each be used as shown.

CreateWebResourceRequestAuthentication and Web Resources

Create a custom HTTP request object. Returns a Long handle for use with NavigateWithCustomRequest or NavigateWithWebResourceRequestSync.

Parameter order: (method, url, headers, postData).

SignaturehReq = m_lv.CreateWebResourceRequest(method, url, headers, postData) As Long
Registeredsupported Reg-Freesupported
VBA
Dim hReq As Long
hReq = m_lv.CreateWebResourceRequest("GET", "https://api.example.com/data", _
    "Authorization: Bearer token123", "")
Debug.Print "Request handle: " & hReq
VBA
Dim hReq As Long
hReq = pool.CreateWebResourceRequest(idx, "GET", "https://api.example.com/data", _
    "Authorization: Bearer token123", "")

See alsoNavigateWithCustomRequest, NavigateWithWebResourceRequestSync

CreateWebResourceResponseAuthentication and Web Resources

Create a custom HTTP response object for use in the WebResourceRequested event. Returns a Long handle.

Parameter order: (body, statusCode, statusText, headers).

SignaturehResp = m_lv.CreateWebResourceResponse(body, statusCode, statusText, headers) As Long
Registeredsupported Reg-Freesupported
VBA
Dim hResp As Long
hResp = m_lv.CreateWebResourceResponse("<h1>Blocked</h1>", 403, "Forbidden", _
    "Content-Type: text/html")
VBA
Dim hResp As Long
hResp = pool.CreateWebResourceResponse(idx, "<h1>Blocked</h1>", 403, "Forbidden", _
    "Content-Type: text/html")

See alsoWebResourceRequested

Basic Authentication

SetBasicAuthCredentialsAuthentication and Web Resources

Set HTTP Basic Authentication credentials for a URI pattern.

Signaturem_lv.SetBasicAuthCredentials uriPattern, username, password
Registeredsupported Reg-Freesupported
VBA
m_lv.SetBasicAuthCredentials "https://api.example.com/*", "username", "password"
m_lv.Navigate "https://api.example.com/dashboard"
VBA
pool.SetBasicAuthCredentials idx, "https://api.example.com/*", "username", "password"
pool.Navigate idx, "https://api.example.com/dashboard"

ClearBasicAuthCredentialsAuthentication and Web Resources

Clear all stored Basic Authentication credentials.

Signaturem_lv.ClearBasicAuthCredentials
Registeredsupported Reg-Freesupported
VBA
m_lv.ClearBasicAuthCredentials
VBA
pool.ClearBasicAuthCredentials idx

Web Resource Filtering and Blocking

AddWebResourceRequestedFilterAuthentication and Web Resources

Add a URL filter for web resource interception.

Second parameter is a resource-type code; the source documents 0 = all resource types and 3 = Image as example values — no complete enumeration of the resource-type codes is given elsewhere in the reviewed source.

Signaturem_lv.AddWebResourceRequestedFilter urlPattern, resourceType
Registeredsupported Reg-Freesupported
VBA
' Block ad networks (0 = all resource types)
m_lv.AddWebResourceRequestedFilter "*.doubleclick.net*", 0
m_lv.AddWebResourceRequestedFilter "*.googlesyndication.com*", 0
' Block only images from a domain (3 = Image)
m_lv.AddWebResourceRequestedFilter "*.ads.example.com*", 3
VBA
pool.AddWebResourceRequestedFilter idx, "*.doubleclick.net*", 0

Gotchas

  • The resource-type code is only illustrated with two example values in the source (0 = all resource types, 3 = Image); no complete enumeration of the codes is given elsewhere in the reviewed source.

See alsoRemoveWebResourceRequestedFilter, SetWebResourceBlocking

RemoveWebResourceRequestedFilterAuthentication and Web Resources

Remove a web resource interception filter (same (urlPattern, resourceType) signature as AddWebResourceRequestedFilter).

Signaturem_lv.RemoveWebResourceRequestedFilter urlPattern, resourceType
Registeredsupported Reg-Freesupported
VBA
m_lv.RemoveWebResourceRequestedFilter "*.doubleclick.net*", 0
VBA
pool.RemoveWebResourceRequestedFilter idx, "*.doubleclick.net*", 0

See alsoAddWebResourceRequestedFilter

ClearAllWebResourceRequestedFiltersAuthentication and Web Resources

Remove all web resource interception filters.

Signaturem_lv.ClearAllWebResourceRequestedFilters
Registeredsupported Reg-Freesupported
VBA
m_lv.ClearAllWebResourceRequestedFilters
VBA
pool.ClearAllWebResourceRequestedFilters idx

SetWebResourceBlockingAuthentication and Web Resources

Enable or disable blocking of matched web resources (matches are established via AddWebResourceRequestedFilter).

Signaturem_lv.SetWebResourceBlocking enabled
Registeredsupported Reg-Freesupported
VBA
m_lv.AddWebResourceRequestedFilter "*.ads.example.com*", 0
m_lv.SetWebResourceBlocking True
VBA
pool.SetWebResourceBlocking idx, True

See alsoAddWebResourceRequestedFilter, IsWebResourceBlockingEnabled

IsWebResourceBlockingEnabledAuthentication and Web Resources

Check if web resource blocking is active. Type: Boolean. Read-only.

Signaturem_lv.IsWebResourceBlockingEnabled As Boolean ' Read-only
Registeredsupported Reg-Freesupported
VBA
Debug.Print "Blocking enabled: " & m_lv.IsWebResourceBlockingEnabled
VBA
Debug.Print "Blocking: " & pool.IsWebResourceBlockingEnabled(idx)

Gotchas

  • Unlike most other Reg-Free equivalents in this category, the Reg-Free form keeps the exact same member name (IsWebResourceBlockingEnabled) rather than a Get-prefixed alias — it is called as a function taking idx.

See alsoSetWebResourceBlocking

GetWebResourceRequestedFiltersAuthentication and Web Resources

Get all active filters as a JSON array (returns String).

Signaturem_lv.GetWebResourceRequestedFilters As String ' JSON array
Registeredsupported Reg-Freesupported
VBA
Debug.Print m_lv.GetWebResourceRequestedFilters
VBA
Debug.Print pool.GetWebResourceRequestedFilters(idx)

Gotchas

  • Not tagged (Property) in the source, unlike the members immediately above and below it.

BlockedRequestCountAuthentication and Web Resources

Get count of blocked requests since last reset. Type: Long. Read-only.

Signaturem_lv.BlockedRequestCount As Long ' Read-only
Registeredsupported Reg-Freesupported
VBA
Debug.Print "Blocked: " & m_lv.BlockedRequestCount
VBA
Dim result As Long
result = pool.GetBlockedRequestCount(idx)
Debug.Print "Blocked: " & result

Gotchas

  • The Reg-Free accessor is named GetBlockedRequestCount, not BlockedRequestCount — the member name itself changes between modes (contrast with IsWebResourceBlockingEnabled above, which keeps its name unchanged in Reg-Free). This is documented as-is in the source, not a contradiction — just an inconsistency in the mode-specific naming convention.

See alsoResetBlockedRequestCount, IsWebResourceBlockingEnabled

ResetBlockedRequestCountAuthentication and Web Resources

Reset the blocked request counter to zero.

Signaturem_lv.ResetBlockedRequestCount
Registeredsupported Reg-Freesupported
VBA
m_lv.ResetBlockedRequestCount
VBA
pool.ResetBlockedRequestCount idx

See alsoBlockedRequestCount

EnableWebResourceResponseTrackingAuthentication and Web Resources

Enable firing of WebResourceResponseReceived events.

Signaturem_lv.EnableWebResourceResponseTracking enabled
Registeredsupported Reg-Freesupported
VBA
m_lv.EnableWebResourceResponseTracking True
VBA
pool.EnableWebResourceResponseTracking idx, True

See alsoWebResourceResponseReceived

Proxy Settings

Both proxy properties are documented as Pre-init only — they must be set before the control/browser instance is initialized; this restriction is not stated for any other member in this category.

ProxyServerAuthentication and Web Resources

Get or set the proxy server. Type: String. Read/Write. Pre-init only.

In Registered mode this is a native property. In Reg-Free mode it is exposed as separate SetProxyServer / GetProxyServer methods (confirmed by the auto-synced API reference, which tags both Mode: Reg-Free Only and declares the return type of GetProxyServer as String).

Signaturem_lv.ProxyServer As String ' Read/Write, Pre-init only
Registeredsupported Reg-Freesupported
VBA
m_lv.ProxyServer = "http://proxy.example.com:8080"
Debug.Print m_lv.ProxyServer
VBA
pool.SetProxyServer idx, "http://proxy.example.com:8080"

Dim result As String
result = pool.GetProxyServer(idx)
Debug.Print result

Gotchas

  • Pre-init only: must be set before the control/browser instance is initialized — a restriction not stated for any other member in this category.
  • Reg-Free mode exposes this as separate SetProxyServer / GetProxyServer methods rather than a single property; confirmed by the auto-synced API reference, which tags both Mode: Reg-Free Only and declares GetProxyServer's return type as String.

See alsoProxyBypassList

ProxyBypassListAuthentication and Web Resources

Proxy bypass list (semicolon-separated). Type: String. Read/Write. Pre-init only.

In Registered mode this is a native property. In Reg-Free mode it is exposed as separate SetProxyBypassList / GetProxyBypassList methods (confirmed by the auto-synced API reference, tagged Mode: Reg-Free Only, GetProxyBypassList returns String).

Signaturem_lv.ProxyBypassList As String ' Read/Write, Pre-init only
Registeredsupported Reg-Freesupported
VBA
m_lv.ProxyBypassList = "localhost;*.local;192.168.*"
VBA
pool.SetProxyBypassList idx, "localhost;*.local;192.168.*"

Dim result As String
result = pool.GetProxyBypassList(idx)

Gotchas

  • Pre-init only: must be set before the control/browser instance is initialized — a restriction not stated for any other member in this category.
  • Reg-Free mode exposes this as separate SetProxyBypassList / GetProxyBypassList methods rather than a single property; confirmed by the auto-synced API reference, tagged Mode: Reg-Free Only, GetProxyBypassList returns String.

See alsoProxyServer

Security and SSO

IgnoreCertificateErrorsAuthentication and Web Resources

Ignore SSL certificate errors. Type: Boolean. Read/Write. Source comment: "USE WITH CAUTION" — dev/test only.

In Registered mode this is a native property. In Reg-Free mode it is exposed as separate SetIgnoreCertificateErrors / GetIgnoreCertificateErrors methods (confirmed by the auto-synced API reference, tagged Mode: Reg-Free Only, GetIgnoreCertificateErrors returns Boolean).

Signaturem_lv.IgnoreCertificateErrors As Boolean ' Read/Write
Registeredsupported Reg-Freesupported
VBA
m_lv.IgnoreCertificateErrors = True   ' USE WITH CAUTION
VBA
pool.SetIgnoreCertificateErrors idx, True

Dim result As Boolean
result = pool.GetIgnoreCertificateErrors(idx)

Gotchas

  • Source comment: "USE WITH CAUTION" — intended for dev/test only.
  • Reg-Free mode exposes this as separate SetIgnoreCertificateErrors / GetIgnoreCertificateErrors methods rather than a single property; confirmed by the auto-synced API reference, tagged Mode: Reg-Free Only, with GetIgnoreCertificateErrors returning Boolean.

AllowSingleSignOnUsingOSPrimaryAccountAuthentication and Web Resources

Enable SSO using the OS primary account for intranet sites. Type: Boolean. Read/Write.

In Registered mode this is a native property. In Reg-Free mode it is exposed as separate SetAllowSingleSignOnUsingOSPrimaryAccount / GetAllowSingleSignOnUsingOSPrimaryAccount methods (confirmed by the auto-synced API reference, tagged Mode: Reg-Free Only, GetAllowSingleSignOnUsingOSPrimaryAccount returns Boolean).

Signaturem_lv.AllowSingleSignOnUsingOSPrimaryAccount As Boolean ' Read/Write
Registeredsupported Reg-Freesupported
VBA
m_lv.AllowSingleSignOnUsingOSPrimaryAccount = True
VBA
pool.SetAllowSingleSignOnUsingOSPrimaryAccount idx, True

Dim result As Boolean
result = pool.GetAllowSingleSignOnUsingOSPrimaryAccount(idx)

Gotchas

  • Reg-Free mode exposes this as separate SetAllowSingleSignOnUsingOSPrimaryAccount / GetAllowSingleSignOnUsingOSPrimaryAccount methods rather than a single property; confirmed by the auto-synced API reference, tagged Mode: Reg-Free Only, GetAllowSingleSignOnUsingOSPrimaryAccount returns Boolean.

HasAuthenticationSupportAuthentication and Web Resources

Check if enhanced authentication features are available. Type: Boolean. Read-only.

Signaturem_lv.HasAuthenticationSupport As Boolean ' Read-only
Registeredsupported Reg-Freesupported
VBA
Debug.Print "Auth support: " & m_lv.HasAuthenticationSupport
VBA
Debug.Print "Auth support: " & pool.HasAuthenticationSupport(idx)

Gotchas

  • Unlike the proxy/certificate/SSO properties above, the Reg-Free form keeps the exact same member name (HasAuthenticationSupport) rather than a Get-prefixed alias — it is called as a function taking idx.
  • No separate auto-synced entry exists for this member beyond what is shown here.

Settings and Browser Behavior

Canonical variables used below: Registered mode = m_lv As LiteView2Lib.LiteView2Ctrl; Reg-Free mode = pool As Object and idx As Long (the browser index returned by the pool's create call).

For every Reg-Free member, the underlying pool call is a Get/Set-prefixed method (or, for two members noted below, an indexed property) taking idx as the first argument. Where the pool method's name drops or adds a word relative to the Registered property name (e.g. property AreDefaultContextMenusEnabled vs. pool method ContextMenusEnabled), that is called out explicitly so a lookup by either name succeeds.

Context Menus, DevTools, and Status Bar

AreDefaultContextMenusEnabledSettings and Browser Behavior

Enable/disable right-click context menus.

SignatureAreDefaultContextMenusEnabled As Boolean ' R/W
Registeredsupported Reg-Freesupported
VBA
Debug.Print m_lv.AreDefaultContextMenusEnabled
m_lv.AreDefaultContextMenusEnabled = False   ' Disable right-click menu
VBA
Debug.Print pool.GetContextMenusEnabled(idx)
pool.SetContextMenusEnabled idx, False

Gotchas

  • The Reg-Free pool method name drops "Default": ContextMenusEnabled, not DefaultContextMenusEnabled.

AreDevToolsEnabledSettings and Browser Behavior

Enable/disable DevTools (F12).

SignatureAreDevToolsEnabled As Boolean ' R/W
Registeredsupported Reg-Freesupported
VBA
m_lv.AreDevToolsEnabled = False   ' Disable F12
VBA
pool.SetDevToolsEnabled idx, False
Debug.Print pool.GetDevToolsEnabled(idx)   ' Get variant, from Additional API Reference

Gotchas

  • The Reg-Free pool method name drops "Are": DevToolsEnabled.

IsStatusBarEnabledSettings and Browser Behavior

Enable/disable the status bar.

SignatureIsStatusBarEnabled As Boolean ' R/W
Registeredsupported Reg-Freesupported
VBA
m_lv.IsStatusBarEnabled = False
VBA
pool.SetStatusBarEnabled idx, False
Debug.Print pool.GetStatusBarEnabled(idx)   ' Get variant, from Additional API Reference

Gotchas

  • The Reg-Free pool method name drops "Is": StatusBarEnabled.

Zoom

ZoomFactorSettings and Browser Behavior

Get or set zoom level.

SignatureZoomFactor As Double ' R/W, 1.0 = 100%
Registeredsupported Reg-Freesupported
VBA
Debug.Print "Zoom: " & m_lv.ZoomFactor * 100 & "%"
m_lv.ZoomFactor = 1.5   ' 150%
VBA
Debug.Print "Zoom: " & pool.GetZoom(idx) * 100 & "%"
pool.SetZoom idx, 1.5

Gotchas

  • Reg-Free pool methods are named Zoom, not ZoomFactor (GetZoom/SetZoom).
  • A related event, ZoomFactorChanged (Registered mode, DISPID 26), fires when the zoom level changes.

See alsoZoomFactorChanged

IsZoomControlEnabledSettings and Browser Behavior

Enable/disable Ctrl+scroll zoom.

SignatureIsZoomControlEnabled As Boolean ' R/W
Registeredsupported Reg-Freesupported
VBA
m_lv.IsZoomControlEnabled = False
VBA
pool.SetIsZoomControlEnabled idx, False
Debug.Print pool.GetIsZoomControlEnabled(idx)   ' Get variant, from Additional API Reference

IsPinchZoomEnabledSettings and Browser Behavior

Enable/disable pinch zoom (touch).

SignatureIsPinchZoomEnabled As Boolean ' R/W
Registeredsupported Reg-Freesupported
VBA
m_lv.IsPinchZoomEnabled = False
VBA
pool.SetIsPinchZoomEnabled idx, False
Debug.Print pool.GetIsPinchZoomEnabled(idx)   ' Get variant, from Additional API Reference

Keyboard, Touch, and Drag/Drop Input

AreBrowserAcceleratorKeysEnabledSettings and Browser Behavior

Enable/disable browser accelerator keys (Ctrl+F, F5, etc.).

SignatureAreBrowserAcceleratorKeysEnabled As Boolean ' R/W
Registeredsupported Reg-Freesupported
VBA
m_lv.AreBrowserAcceleratorKeysEnabled = False
VBA
pool.SetAreBrowserAcceleratorKeysEnabled idx, False
Debug.Print pool.GetAreBrowserAcceleratorKeysEnabled(idx)   ' Get variant, from Additional API Reference

IsSwipeNavigationEnabledSettings and Browser Behavior

Enable/disable swipe navigation (touch back/forward).

SignatureIsSwipeNavigationEnabled As Boolean ' R/W
Registeredsupported Reg-Freesupported
VBA
m_lv.IsSwipeNavigationEnabled = False
VBA
pool.SetIsSwipeNavigationEnabled idx, False
Debug.Print pool.GetIsSwipeNavigationEnabled(idx)   ' Get variant, from Additional API Reference

IsDragDropEnabledSettings and Browser Behavior

Enable/disable drag and drop.

SignatureIsDragDropEnabled As Boolean ' Write-only
Registeredsupported Reg-Freesupported
VBA
m_lv.IsDragDropEnabled = False
VBA
pool.IsDragDropEnabled(idx) = False

Gotchas

  • Write-only — there is no getter for this property.
  • Reg-Free uses indexed property assignment, not a Set-prefixed method — this differs from the calling convention used by every other member in this category.

Browser Identity

UserAgentSettings and Browser Behavior

Get or set the user agent string.

SignatureUserAgent As String ' R/W
Registeredsupported Reg-Freesupported
VBA
Debug.Print m_lv.UserAgent
m_lv.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) MyApp/1.0"
VBA
Debug.Print pool.GetUserAgent(idx)
pool.SetUserAgent idx, "Mozilla/5.0 MyApp/1.0"

LanguageSettings and Browser Behavior

Preferred language (BCP 47).

SignatureLanguage As String ' R/W, pre-init only
Registeredsupported Reg-Freesupported
VBA
m_lv.Language = "de-DE"
Debug.Print m_lv.Language
VBA
pool.SetLanguage idx, "de-DE"
Debug.Print pool.GetLanguage(idx)

Gotchas

  • Pre-init only.
  • The Additional API Reference entry for SetLanguage explicitly repeats the pre-init restriction ("Set preferred language (BCP 47) for the browser. Pre-init only.") — set it before the browser for this index is created.

Script Dialogs and Error Pages

DefaultScriptDialogsEnabledSettings and Browser Behavior

Enable/disable default script dialogs (alert, confirm, prompt).

SignatureDefaultScriptDialogsEnabled As Boolean ' R/W
Registeredsupported Reg-Freesupported
VBA
m_lv.DefaultScriptDialogsEnabled = False  ' Suppress JS alert/confirm
VBA
pool.SetDefaultScriptDialogsEnabled idx, False
Debug.Print pool.GetDefaultScriptDialogsEnabled(idx)   ' Get variant, from Additional API Reference

IsBuiltInErrorPageEnabledSettings and Browser Behavior

Enable/disable built-in error pages.

SignatureIsBuiltInErrorPageEnabled As Boolean ' R/W
Registeredsupported Reg-Freesupported
VBA
m_lv.IsBuiltInErrorPageEnabled = False   ' Show custom error handling
VBA
pool.SetBuiltInErrorPageEnabled idx, False
Debug.Print pool.GetBuiltInErrorPageEnabled(idx)   ' Get variant, from Additional API Reference

Gotchas

  • The Reg-Free pool method name drops "Is": BuiltInErrorPageEnabled.

Autofill and Password Autosave

Two scopes exist for both settings: the plain (browser-instance-level) property and a Profile-prefixed (profile-level) property. Both are documented identically in the source apart from the "Profile" qualifier — no additional distinction is given.

IsPasswordAutosaveEnabledSettings and Browser Behavior

Enable/disable password autosave.

SignatureIsPasswordAutosaveEnabled As Boolean ' R/W
Registeredsupported Reg-Freesupported
VBA
m_lv.IsPasswordAutosaveEnabled = False
VBA
pool.SetIsPasswordAutosaveEnabled idx, False
Debug.Print pool.GetIsPasswordAutosaveEnabled(idx)   ' Get variant, from Additional API Reference

IsGeneralAutofillEnabledSettings and Browser Behavior

Enable/disable general form autofill.

SignatureIsGeneralAutofillEnabled As Boolean ' R/W
Registeredsupported Reg-Freesupported
VBA
m_lv.IsGeneralAutofillEnabled = False
VBA
pool.SetIsGeneralAutofillEnabled idx, False
Debug.Print pool.GetIsGeneralAutofillEnabled(idx)   ' Get variant, from Additional API Reference

ProfileIsPasswordAutosaveEnabledSettings and Browser Behavior

Profile-level password autosave.

SignatureProfileIsPasswordAutosaveEnabled As Boolean ' R/W
Registeredsupported Reg-Freesupported
VBA
m_lv.ProfileIsPasswordAutosaveEnabled = False
VBA
pool.SetProfileIsPasswordAutosaveEnabled idx, False
Debug.Print pool.GetProfileIsPasswordAutosaveEnabled(idx)   ' Get variant, from Additional API Reference

ProfileIsGeneralAutofillEnabledSettings and Browser Behavior

Profile-level general autofill.

SignatureProfileIsGeneralAutofillEnabled As Boolean ' R/W
Registeredsupported Reg-Freesupported
VBA
m_lv.ProfileIsGeneralAutofillEnabled = False
VBA
pool.SetProfileIsGeneralAutofillEnabled idx, False
Debug.Print pool.GetProfileIsGeneralAutofillEnabled(idx)   ' Get variant, from Additional API Reference

PDF Toolbar

HiddenPdfToolbarItemsSettings and Browser Behavior

Hide specific PDF toolbar items (bitmask).

SignatureHiddenPdfToolbarItems As Long ' R/W, bitmask
Registeredsupported Reg-Freesupported
VBA
' Hide Save and Print buttons: LV2_PDF_SAVE(1) + LV2_PDF_PRINT(2) = 3
m_lv.HiddenPdfToolbarItems = 3
VBA
pool.SetHiddenPdfToolbarItems idx, 3
Debug.Print pool.GetHiddenPdfToolbarItems(idx)   ' Get variant, from Additional API Reference

Security and Privacy

IsReputationCheckingRequiredSettings and Browser Behavior

SmartScreen reputation checking for downloads.

SignatureIsReputationCheckingRequired As Boolean ' R/W
Registeredsupported Reg-Freesupported
VBA
m_lv.IsReputationCheckingRequired = False
VBA
pool.SetIsReputationCheckingRequired idx, False
Debug.Print pool.GetIsReputationCheckingRequired(idx)   ' Get variant, from Additional API Reference

PreferredTrackingPreventionLevelSettings and Browser Behavior

Tracking prevention level.

SignaturePreferredTrackingPreventionLevel As LV2_TRACKING_PREVENTION ' R/W, 0-3
Registeredsupported Reg-Freesupported
VBA
m_lv.PreferredTrackingPreventionLevel = 3  ' Strict
VBA
pool.SetPreferredTrackingPreventionLevel idx, 3
Dim result As LV2_TRACKING_PREVENTION
result = pool.GetPreferredTrackingPreventionLevel(idx)

Gotchas

  • The Additional API Reference entry types the Reg-Free getter's return explicitly as LV2_TRACKING_PREVENTION.

See alsoLV2_TRACKING_PREVENTION (Enums Reference)

Appearance

PreferredColorSchemeSettings and Browser Behavior

Color scheme preference.

SignaturePreferredColorScheme As LV2_COLOR_SCHEME ' R/W, 0=Auto 1=Light 2=Dark
Registeredsupported Reg-Freesupported
VBA
m_lv.PreferredColorScheme = 2  ' Force dark mode
VBA
pool.SetPreferredColorScheme idx, 2
Dim result As LV2_COLOR_SCHEME
result = pool.GetPreferredColorScheme(idx)

Gotchas

  • The Additional API Reference entry types the Reg-Free getter's return explicitly as LV2_COLOR_SCHEME.

See alsoLV2_COLOR_SCHEME (Enums Reference)

NonClientRegionSupportEnabledSettings and Browser Behavior

Enable non-client region support (custom title bar).

SignatureNonClientRegionSupportEnabled As Boolean ' R/W
Registeredsupported Reg-Freesupported
VBA
m_lv.NonClientRegionSupportEnabled = True
VBA
pool.SetNonClientRegionSupportEnabled idx, True
Debug.Print pool.GetNonClientRegionSupportEnabled(idx)   ' Get variant, from Additional API Reference

SetDefaultBackgroundColorSettings and Browser Behavior

Set the default background color (ARGB format).

Signaturepool.SetDefaultBackgroundColor idx, argb As Long ' Reg-Free only
Registerednot available Reg-Freesupported
VBA
' Not available as direct method in registered mode
VBA
pool.SetDefaultBackgroundColor idx, &HFFFFFFFF  ' White
pool.SetDefaultBackgroundColor idx, &H00000000  ' Transparent

Gotchas

  • Not available as a direct method in Registered mode.

Pre-Init Startup Configuration

The four members below must be set before the underlying WebView2 environment is created — in Registered mode, before WebViewReady fires (e.g., in Form_Load); in Reg-Free mode, before the pool's create call for that browser (CreateInControl).

AdditionalBrowserArgumentsSettings and Browser Behavior

Chromium command-line arguments.

SignatureAdditionalBrowserArguments As String ' R/W, pre-init only
Registeredsupported Reg-Freesupported
VBA
' Set BEFORE WebViewReady fires (e.g., in Form_Load)
m_lv.AdditionalBrowserArguments = "--disable-features=msSmartScreenProtection"
VBA
pool.AdditionalBrowserArguments = "--disable-features=msSmartScreenProtection"
' Must be set before CreateInControl

Gotchas

  • Pre-init only — must be set before WebViewReady fires in Registered mode (e.g., in Form_Load), or before the pool's CreateInControl call in Reg-Free mode.

EnableHardwareAccelerationSettings and Browser Behavior

Enable/disable GPU acceleration.

SignatureEnableHardwareAcceleration As Boolean ' R/W, pre-init only
Registeredsupported Reg-Freesupported
VBA
m_lv.EnableHardwareAcceleration = False  ' Disable GPU (troubleshooting)
VBA
pool.EnableHardwareAcceleration = False

Gotchas

  • Pre-init only — must be set before the underlying WebView2 environment is created (before WebViewReady in Registered mode; before CreateInControl in Reg-Free mode).

BrowserExecutableFolderSettings and Browser Behavior

Path to fixed-version WebView2 runtime.

SignatureBrowserExecutableFolder As String ' R/W, pre-init only
Registeredsupported Reg-Freesupported
VBA
m_lv.BrowserExecutableFolder = "C:\WebView2Runtime\130.0.0.0"
VBA
pool.BrowserExecutableFolder = "C:\WebView2Runtime\130.0.0.0"

Gotchas

  • Pre-init only — must be set before the underlying WebView2 environment is created (before WebViewReady in Registered mode; before CreateInControl in Reg-Free mode).

RequiredMinimumVersionSettings and Browser Behavior

Minimum WebView2 runtime version required.

SignatureRequiredMinimumVersion As String ' R/W, pre-init only
Registeredsupported Reg-Freenot available
VBA
m_lv.RequiredMinimumVersion = "120.0.0.0"
VBA
' Not available in pool

Gotchas

  • Pre-init only.
  • Not available in the pool.

Resizing and Resource Usage

SmartResizeSettings and Browser Behavior

Auto-fit WebView when control is resized.

SignatureSmartResize As Boolean ' R/W, default True
Registeredsupported Reg-Freenot available (pool uses Resize)
VBA
m_lv.SmartResize = False  ' Manage size manually
VBA
' Not available in pool - pool uses Resize method

Gotchas

  • Not available in the pool API — the pool uses a Resize method instead.

MemoryUsageTargetLevelSettings and Browser Behavior

Memory usage target.

SignatureMemoryUsageTargetLevel As Long ' R/W, 0=Normal 1=Low
Registeredsupported Reg-Freesupported
VBA
m_lv.MemoryUsageTargetLevel = 1  ' Low memory mode
VBA
pool.MemoryUsageTargetLevel(idx) = 1

Gotchas

  • Reg-Free uses indexed property assignment, not a Set-prefixed method — the same convention as IsDragDropEnabled above.

See alsoIsDragDropEnabled

VB6 Compatibility and Crash Recovery

EventsUseHexadecimalSettings and Browser Behavior

Use hex strings for large integers in events (VB6 compatibility).

SignatureEventsUseHexadecimal As Boolean ' R/W
Registeredsupported Reg-Freenot applicable
VBA
m_lv.EventsUseHexadecimal = True
' Events will now fire Hex variants (e.g., NavigationCompletedHex)
VBA
' Not applicable - pool uses different event mechanism

Gotchas

  • Not applicable in Reg-Free mode — the pool uses a different event mechanism.

AutoRecoverOnCrashSettings and Browser Behavior

Auto-recover WebView on renderer crash.

SignatureAutoRecoverOnCrash As Boolean ' R/W
Registeredsupported Reg-Freenot available (handle ProcessFailed)
VBA
m_lv.AutoRecoverOnCrash = True
VBA
' Not available in pool - handle ProcessFailed manually

Gotchas

  • Not available in the pool API — handle the ProcessFailed event manually in Reg-Free mode.

See alsoProcessFailed

The following two properties were confirmed present in the source (lines 5417-5445) but not captured under any category during the first drafting pass; added here during the completeness audit so Part II remains an exhaustive reference.

PopupModeSettings and Browser Behavior

Popup handling mode.

SignaturePopupMode As LV2_POPUP_MODE ' R/W, 0=Allow 1=Block 2=SameWindow
Registeredsupported Reg-Freesupported
VBA
' Registered
m_lv.PopupMode = 1   ' Block all popups
VBA
' Reg-Free
pool.SetPopupMode idx, 1
Dim mode As Long
mode = pool.GetPopupMode(idx)

See alsoLV2_POPUP_MODE (Enums Reference)

OpenPopupsInSameWindowSettings and Browser Behavior

Navigate popups in the same window instead of opening a new one.

SignatureOpenPopupsInSameWindow As Boolean ' R/W
Registeredsupported Reg-Freesupported
VBA
' Registered
m_lv.OpenPopupsInSameWindow = True
VBA
' Reg-Free
pool.SetOpenPopupsInSameWindow idx, True
Dim same As Boolean
same = pool.GetOpenPopupsInSameWindow(idx)

Find-in-Page

The following find-in-page methods and properties were confirmed present in the source (lines 4748-4816) but not captured under any category during the first drafting pass; added here during the completeness audit. Taught briefly in Part I, Chapter 11.

StartFindSettings and Browser Behavior

Start finding text in the current page.

Parameters: search text, case-sensitive (Boolean), whole-word-only (Boolean).

SignatureStartFind(searchText As String, caseSensitive As Boolean, wholeWordOnly As Boolean)
Registeredsupported Reg-Freesupported
VBA
' Registered
m_lv.StartFind "search term", False, False   ' case-insensitive, partial match
VBA
' Reg-Free
pool.StartFind idx, "search term", False, False

FindNext / FindPreviousSettings and Browser Behavior

Navigate between find matches.

SignatureFindNext() / FindPrevious()
Registeredsupported Reg-Freesupported
VBA
' Registered
m_lv.FindNext
m_lv.FindPrevious
VBA
' Reg-Free
pool.FindNext idx
pool.FindPrevious idx

StopFindSettings and Browser Behavior

Stop the find session.

Parameter: clearSelection (False = keep the current match selected/highlighted, True = clear it).

SignatureStopFind(clearSelection As Boolean)
Registeredsupported Reg-Freesupported
VBA
' Registered
m_lv.StopFind False
VBA
' Reg-Free
pool.StopFind idx, False

Find PropertiesSettings and Browser Behavior

Find-in-page state and behavior properties: FindMatchCount, FindActiveMatchIndex, IsFindActive, SuppressFindUI, FindHighlightAllMatches.

SignatureFindMatchCount As Long (R); FindActiveMatchIndex As Long (R); IsFindActive As Boolean (R); SuppressFindUI As Boolean (R/W); FindHighlightAllMatches As Boolean (R/W)
Registeredsupported Reg-Freesupported
VBA
' Registered
Debug.Print "Matches: " & m_lv.FindMatchCount
Debug.Print "Active: " & m_lv.FindActiveMatchIndex
Debug.Print "Active session: " & m_lv.IsFindActive
m_lv.SuppressFindUI = True
m_lv.FindHighlightAllMatches = True
VBA
' Reg-Free
Debug.Print "Matches: " & pool.GetFindMatchCount(idx)
Debug.Print "Active: " & pool.GetFindActiveMatchIndex(idx)
Debug.Print "Active session: " & pool.IsFindActive(idx)
pool.SetSuppressFindUI idx, True
pool.SetFindHighlightAllMatches idx, True
Dim suppressed As Boolean, highlightAll As Boolean
suppressed = pool.GetSuppressFindUI(idx)
highlightAll = pool.GetFindHighlightAllMatches(idx)

Gotchas

  • FindMatchCount, FindActiveMatchIndex, and IsFindActive are read-only; SuppressFindUI and FindHighlightAllMatches are read/write.

Profiles, Sessions and Multiple Instances

Reg-Free pool mode manages multiple independent browser instances, each addressable by an integer index (idx) returned at creation time. Each instance can optionally be bound to a named, on-disk profile for session isolation, including an InPrivate variant. Registered mode manages a single browser per control instance but adds its own set of embedding/window-management members for placing that single browser into an external native window. WebView2 runtime detection and browser-extension enumeration are also documented here.

Create / CreateInControlProfiles, Sessions and Multiple Instances

Create a new browser in the Reg-Free pool.

Returns the integer index used to address that browser in every subsequent pool call.

Signatureidx = pool.Create(hwndParent, url, x, y, width, height)
Registerednot available Reg-Freesupported
VBA
Dim idx As Long
idx = pool.Create(Me.hWnd, "https://example.com", 10, 10, 800, 600)
' Or embedded directly in a VBA control at creation time:
idx = pool.CreateInControl("about:blank", Me.FraBrowser)

CreateWithProfile / CreateInControlWithProfile / CreateWithProfileInPrivateProfiles, Sessions and Multiple Instances

Create a pool browser bound to a named profile, for session isolation across instances.

  • CreateWithProfile — create browser with a named profile for session isolation.
  • CreateInControlWithProfile — create browser with profile and embed it directly in a VBA control.
  • CreateWithProfileInPrivate — create browser with a named profile, in InPrivate mode.

All three return the new browser's index (Long).

Signatureidx = pool.CreateWithProfile(hwndParent, url, x, y, width, height, profileName)
Registerednot available Reg-Freesupported
VBA
Dim idx As Long
idx = pool.CreateWithProfile(Me.hWnd, "about:blank", 0, 0, 800, 600, "ProfileA")
idx = pool.CreateInControlWithProfile("about:blank", Me.FraBrowser, "ProfileA")
idx = pool.CreateWithProfileInPrivate(Me.hWnd, "about:blank", 0, 0, 800, 600, "Private1")

Gotchas

  • Parameter order for CreateWithProfile / CreateWithProfileInPrivate: hwndParent, url, x, y, width, height, profileName. CreateInControlWithProfile: url, control, profileName.

Destroy / DestroySync / Park / DestroyAllParkedProfiles, Sessions and Multiple Instances

Lifecycle control for pool browser instances.

  • Destroy — destroys the browser asynchronously.
  • DestroySync — destroys the browser synchronously.
  • Park — hides the browser instance without destroying it, so it can be reused later.
  • DestroyAllParked — destroys every currently-parked browser at once.
Signaturepool.Destroy browserIndex
Registerednot available Reg-Freesupported
VBA
pool.Destroy idx              ' Async destroy
pool.DestroySync idx          ' Sync destroy
pool.Park idx                 ' Hide for reuse
pool.DestroyAllParked         ' Cleanup parked

GetParkedBrowserCount / GetBrowserCountProfiles, Sessions and Multiple Instances

Instance counters for the pool.

GetParkedBrowserCount returns the number of browsers currently parked (hidden, held for reuse via Park). GetBrowserCount returns the total number of browsers currently held by the pool.

Signaturepool.GetBrowserCount
Registerednot available Reg-Freesupported
VBA
Debug.Print pool.GetParkedBrowserCount
Debug.Print pool.GetBrowserCount

Resize / EmbedInControl / ReparentProfiles, Sessions and Multiple Instances

Positioning and re-embedding operations for an existing pool browser, addressed by index.

  • Resize — resize browser. Signature: pool.Resize browserIndex, x, y, width, height.
  • EmbedInControl — embed browser into a VBA control (Frame, Image, etc.). Signature: pool.EmbedInControl browserIndex, control.
  • Reparent — reparent browser to a new window. Signature: pool.Reparent browserIndex, hwndNewParent, x, y, width, height.
Signaturepool.Resize browserIndex, x, y, width, height
Registerednot available Reg-Freesupported
VBA
pool.Resize idx, 0, 0, 1024, 768
pool.EmbedInControl idx, Me.FraOtherFrame
pool.Reparent idx, newHwnd, 0, 0, 800, 600

GetProfileName / GetProfilePathProfiles, Sessions and Multiple Instances

Profile identity lookups for a pool browser.

GetProfileName — get the profile name of a browser. GetProfilePath — get the on-disk profile path.

Signaturepool.GetProfileName(browserIndex)
Registerednot available Reg-Freesupported
VBA
Debug.Print pool.GetProfileName(idx)
Debug.Print pool.GetProfilePath(idx)

ClearProfileBrowsingData / ClearProfileBrowsingDataAllProfiles, Sessions and Multiple Instances

Clear browsing data belonging to a pool browser's profile.

ClearProfileBrowsingData — clear specific browsing data for a browser's profile (takes a dataKinds value; the source example uses 16384). ClearProfileBrowsingDataAll — clear ALL browsing data for a browser's profile.

Signaturepool.ClearProfileBrowsingData browserIndex, dataKinds
Registerednot available Reg-Freesupported
VBA
pool.ClearProfileBrowsingData idx, 16384   ' dataKinds bitmask
pool.ClearProfileBrowsingDataAll idx

IsWebView2RuntimeInstalled / GetWebView2RuntimeVersion / GetWebView2RuntimePathProfiles, Sessions and Multiple Instances

WebView2 runtime detection, independent of any browser instance.

  • IsWebView2RuntimeInstalled — check whether the WebView2 runtime is installed; explicitly documented as usable with no browser needed. Returns Boolean.
  • GetWebView2RuntimeVersion — get the installed WebView2 runtime version string. Returns String.
  • GetWebView2RuntimePath — get the WebView2 runtime install path from the registry. Returns String.
Signaturepool.IsWebView2RuntimeInstalled
Registerednot available Reg-Freesupported
VBA
If pool.IsWebView2RuntimeInstalled Then
    Debug.Print "Version: " & pool.GetWebView2RuntimeVersion
    Debug.Print "Path: " & pool.GetWebView2RuntimePath
End If

GetBrowserExtensionListProfiles, Sessions and Multiple Instances

Get browser extensions list as a JSON array (requires Profile7/8, per the auto-synced description).

Signaturepool.GetBrowserExtensionList(browserIndex)
Registereddocumented two ways Reg-Freesupported
VBA
Debug.Print pool.GetBrowserExtensionList(idx)
VBA
' Registered (per auto-synced section only — not corroborated elsewhere):
Dim result As String
result = m_lv.GetBrowserExtensionList()

' Reg-Free:
Dim result As String
result = pool.GetBrowserExtensionList(idx)

Gotchas

  • Source conflict, flagged but not resolved: the manually-curated reference (line ~4895, heading "Pool-Only: GetBrowserExtensionList") documents this member as Reg-Free only. The auto-synced IDL reference (line ~7062) documents it as Both (Registered + Reg-Free) and supplies a Registered-mode signature that does not appear anywhere in the manually-curated section.
  • Both forms are reproduced here as documented; do not treat either one as authoritative over the other without checking the actual IDL/typelib.
  • Per the manually-curated section, the mode is Reg-Free only.
  • Per the auto-synced IDL section, the mode is Both (Registered + Reg-Free); the Registered-mode call shown above is per that section only and is not corroborated elsewhere.

EmbedInHwnd / EmbedInHwndByLongProfiles, Sessions and Multiple Instances

Embed the (single, Registered-mode) browser in an external, non-VBA window handle.

  • EmbedInHwnd — takes the parent handle as LngLng (64-bit). Auto-synced description text: "Embed browser in an external window handle for reg-free usage" (description text as documented, despite the member itself being tagged Registered Only).
  • EmbedInHwndByLong — takes the parent handle as Long (32-bit), for VB6/VFP compatibility where LngLng is unavailable.

Both signatures: width, height follow the handle parameter.

Signaturem_lv.EmbedInHwnd hwndParent, width, height
Registeredsupported Reg-Freenot available
VBA
m_lv.EmbedInHwnd CLngLng(hwndParent), 800, 600
m_lv.EmbedInHwndByLong CLng(hwndParent), 800, 600   ' VB6 compat

Gotchas

  • The auto-synced description text for EmbedInHwnd reads "Embed browser in an external window handle for reg-free usage" even though the member itself is tagged Registered Only — a documented inconsistency in the source text.

ResizeEmbedded / MoveEmbedded / CloseEmbeddedProfiles, Sessions and Multiple Instances

Manage the embedded browser window created via EmbedInHwnd / EmbedInHwndByLong (or the control's normal embedding).

  • ResizeEmbedded — resize the embedded browser to new dimensions. Signature: width, height.
  • MoveEmbedded — move the embedded browser to a new position. Signature: left, top.
  • CloseEmbedded — close and destroy the embedded browser window. No parameters.
Signaturem_lv.ResizeEmbedded width, height
Registeredsupported Reg-Freenot available
VBA
m_lv.ResizeEmbedded 1024, 768
m_lv.MoveEmbedded 100, 50
m_lv.CloseEmbedded

See alsoEmbedInHwnd, EmbedInHwndByLong

DevTools, CDP, Stealth, Captcha and Office/Document Preview

DevTools & Chrome DevTools Protocol (CDP)

ToggleBridgeInspectorDevTools, CDP, Stealth, Captcha and Office/Document Preview

Toggle the Bridge Inspector HUD, which shows live JS <-> VBA message traffic.

Signaturem_lv.ToggleBridgeInspector
Registeredsupported Reg-Freesupported
VBA
m_lv.ToggleBridgeInspector
VBA
pool.ToggleBridgeInspector idx

OpenDevToolsWindowDevTools, CDP, Stealth, Captcha and Office/Document Preview

Open Chrome DevTools (F12).

Signaturem_lv.OpenDevToolsWindow
Registeredsupported Reg-Freesupported
VBA
m_lv.OpenDevToolsWindow
VBA
pool.OpenDevToolsWindow idx

CallDevToolsProtocolMethodDevTools, CDP, Stealth, Captcha and Office/Document Preview

Execute a Chrome DevTools Protocol method.

First argument is the CDP method name, second is the CDP params encoded as a JSON string. Returns the CDP result as a JSON string.

Waits for the browser's answer (fixed 30 s). Works from ordinary code and inside DevToolsProtocolEventReceived, which is how you answer a CDP event. Inside WebViewReady, other inline events and host-object methods it fails at once with &H80040203 and sends nothing. Reg-Free: a refused call raises &H80004005; GetLastErrorCode(idx) returns &H80040203.

Signatureresult = m_lv.CallDevToolsProtocolMethod(cdpMethod, paramsJson)
Registeredsupported Reg-Freesupported
VBA
Dim result As String
result = m_lv.CallDevToolsProtocolMethod("Page.captureScreenshot", "{""format"":""png""}")
Debug.Print result
VBA
Dim result As String
result = pool.CallDevToolsProtocolMethod(idx, "Page.captureScreenshot", "{""format"":""png""}")

AddDevToolsProtocolEventHandlerDevTools, CDP, Stealth, Captcha and Office/Document Preview

Subscribe to a Chrome DevTools Protocol event by name.

Per the source's own comment, this causes the DevToolsProtocolEventReceived event to fire on matching CDP traffic (event documented in the Events reference, not here).

Mode: Registered (events are delivered). The pool accepts the call, but it raises no events, so nothing is delivered in Reg-Free mode.

Signaturem_lv.AddDevToolsProtocolEventHandler eventName
Registeredsupported Reg-Freeaccepted, no events delivered
VBA
m_lv.AddDevToolsProtocolEventHandler "Network.requestWillBeSent"
' Will fire DevToolsProtocolEventReceived event
VBA
pool.AddDevToolsProtocolEventHandler idx, "Network.requestWillBeSent"   ' accepted, but no event is ever delivered

See alsoDevToolsProtocolEventReceived, RemoveDevToolsProtocolEventHandler

RemoveDevToolsProtocolEventHandlerDevTools, CDP, Stealth, Captcha and Office/Document Preview

Unsubscribe from a DevTools Protocol event previously registered with AddDevToolsProtocolEventHandler.

Signaturem_lv.RemoveDevToolsProtocolEventHandler eventName
Registeredsupported Reg-Freesupported
VBA
m_lv.RemoveDevToolsProtocolEventHandler "Network.requestWillBeSent"
VBA
pool.RemoveDevToolsProtocolEventHandler idx, "Network.requestWillBeSent"

See alsoAddDevToolsProtocolEventHandler

HasDevToolsProtocolDevTools, CDP, Stealth, Captcha and Office/Document Preview

Check if DevTools Protocol is available.

Type: Boolean. Read-only.

Signaturem_lv.HasDevToolsProtocol
Registeredsupported Reg-Freesupported
VBA
Debug.Print "CDP available: " & m_lv.HasDevToolsProtocol
VBA
Debug.Print "CDP available: " & pool.HasDevToolsProtocol(idx)

Stealth / Anti-Detection

EnableStealthModeDevTools, CDP, Stealth, Captcha and Office/Document Preview

Enable comprehensive anti-detection (hides all automation markers at once).

Signaturem_lv.EnableStealthMode enable
Registeredsupported Reg-Freesupported
VBA
m_lv.EnableStealthMode True
VBA
pool.EnableStealthMode idx, True

HideWebDriverDevTools, CDP, Stealth, Captcha and Office/Document Preview

Remove the navigator.webdriver flag.

Signaturem_lv.HideWebDriver enable
Registeredsupported Reg-Freesupported
VBA
m_lv.HideWebDriver True
VBA
pool.HideWebDriver idx, True

SpoofWebGLDevTools, CDP, Stealth, Captcha and Office/Document Preview

Spoof WebGL vendor and renderer strings.

Parameters per the documented example: vendor string, renderer string.

Signaturem_lv.SpoofWebGL vendor, renderer
Registeredsupported Reg-Freesupported
VBA
m_lv.SpoofWebGL "Intel Inc.", "Intel Iris OpenGL Engine"
VBA
pool.SpoofWebGL idx, "Intel Inc.", "Intel Iris OpenGL Engine"

RandomizeCanvasFingerprintDevTools, CDP, Stealth, Captcha and Office/Document Preview

Add noise to the canvas fingerprint to randomize it.

Signaturem_lv.RandomizeCanvasFingerprint enable
Registeredsupported Reg-Freesupported
VBA
m_lv.RandomizeCanvasFingerprint True
VBA
pool.RandomizeCanvasFingerprint idx, True

SpoofScreenSizeDevTools, CDP, Stealth, Captcha and Office/Document Preview

Spoof screen dimensions for fingerprint evasion.

The source documents no named parameters beyond the example call: three numeric arguments (1920, 1080, 24 in the example) with no explicit labels given in the text — presumably width, height, and a bit-depth/color-depth value, but this is not stated outright in the source.

Signaturem_lv.SpoofScreenSize width, height, colorDepth
Registeredsupported Reg-Freesupported
VBA
m_lv.SpoofScreenSize 1920, 1080, 24
VBA
pool.SpoofScreenSize idx, 1920, 1080, 24

Gotchas

  • The three numeric parameters (1920, 1080, 24 in the documented example) are not individually named in the source — they are presumed to be width, height, and a bit-depth/color-depth value, but the source does not state this outright.

DisableWebRTCDevTools, CDP, Stealth, Captcha and Office/Document Preview

Disable WebRTC to prevent IP address leaks.

Signaturem_lv.DisableWebRTC enable
Registeredsupported Reg-Freesupported
VBA
m_lv.DisableWebRTC True
VBA
pool.DisableWebRTC idx, True

EnableMouseNoiseDevTools, CDP, Stealth, Captcha and Office/Document Preview

Add human-like noise to mouse movement events.

Signaturem_lv.EnableMouseNoise enable
Registeredsupported Reg-Freesupported
VBA
m_lv.EnableMouseNoise True
VBA
pool.EnableMouseNoise idx, True

EnableTimingNoiseDevTools, CDP, Stealth, Captcha and Office/Document Preview

Add random delays to actions for human-like timing.

Parameters per the documented example and its inline comment: min delay (ms), max delay (ms) — the example uses a 50-200ms range.

Signaturem_lv.EnableTimingNoise minDelayMs, maxDelayMs
Registeredsupported Reg-Freesupported
VBA
m_lv.EnableTimingNoise 50, 200   ' 50-200ms random delays
VBA
pool.EnableTimingNoise idx, 50, 200

IsStealthEnabled / GetIsStealthEnabledDevTools, CDP, Stealth, Captcha and Office/Document Preview

Check if stealth mode is enabled.

Type: Boolean. Read-only.

Signaturem_lv.IsStealthEnabled
Registeredsupported Reg-Freedocumented two ways
VBA
Debug.Print "Stealth: " & m_lv.IsStealthEnabled
VBA
Debug.Print "Stealth: " & pool.IsStealthEnabled(idx)
VBA
Dim result As Boolean
result = pool.GetIsStealthEnabled(idx)

Contradiction

The Reg-Free member for reading stealth status is documented two different ways in the source: as an indexed property IsStealthEnabled(idx) in the main API reference, and as a Get-prefixed method GetIsStealthEnabled(idx) in the auto-synced IDL reference. These are not two modes of the same call — they are two different spellings claimed for the same Reg-Free functionality, and the source does not reconcile them. The IDL-derived name (GetIsStealthEnabled) is more likely to reflect the actual compiled type-library member; verify against the type library before depending on either name in new code.

Gotchas

  • Reg-Free mode's status-reading member is documented under two different names in different parts of the source: pool.IsStealthEnabled(idx) (main API reference, lines 4904-5158) and pool.GetIsStealthEnabled(idx) (auto-synced IDL reference, tagged Mode: Reg-Free Only, description "Get stealth mode enabled status").
  • The source does not reconcile these two spellings; the IDL-derived name GetIsStealthEnabled is more likely to match the actual compiled type library, so verify against the type library before depending on either name.

See alsoEnableStealthMode

CAPTCHA

SetCaptchaServiceDevTools, CDP, Stealth, Captcha and Office/Document Preview

Configure a CAPTCHA solving service.

Parameters per the example: service name string (e.g. "2captcha"), API key string.

Signaturem_lv.SetCaptchaService serviceName, apiKey
Registeredsupported Reg-Freesupported
VBA
m_lv.SetCaptchaService "2captcha", "YOUR_API_KEY_HERE"
VBA
pool.SetCaptchaService idx, "2captcha", "YOUR_API_KEY_HERE"

DetectCaptchaDevTools, CDP, Stealth, Captcha and Office/Document Preview

Detect CAPTCHA on the current page.

Returns a JSON string with type, siteKey, pageUrl.

Signatureinfo = m_lv.DetectCaptcha
Registeredsupported Reg-Freesupported
VBA
Dim info As String
info = m_lv.DetectCaptcha
Debug.Print "CAPTCHA info: " & info
VBA
Dim info As String
info = pool.DetectCaptcha(idx)

SolveCaptchaDevTools, CDP, Stealth, Captcha and Office/Document Preview

Auto-solve a detected CAPTCHA (detect + solve + submit token in one call).

Parameter: timeout in milliseconds. Returns Boolean success.

Signaturesolved = m_lv.SolveCaptcha(timeoutMs)
Registeredsupported Reg-Freesupported
VBA
Dim solved As Boolean
solved = m_lv.SolveCaptcha(30000)   ' 30 second timeout
If solved Then Debug.Print "CAPTCHA solved!"
VBA
Dim solved As Boolean
solved = pool.SolveCaptcha(idx, 30000)

SolveRecaptchaV2DevTools, CDP, Stealth, Captcha and Office/Document Preview

Solve reCAPTCHA v2 given a known siteKey, and get the token back.

Parameters: siteKey string, page URL string. Returns the token as a String.

Signaturetoken = m_lv.SolveRecaptchaV2(siteKey, pageUrl)
Registeredsupported Reg-Freesupported
VBA
Dim token As String
token = m_lv.SolveRecaptchaV2("6Le-SITE-KEY", "https://www.example.com/form")
Debug.Print "Token: " & token
VBA
Dim token As String
token = pool.SolveRecaptchaV2(idx, "6Le-SITE-KEY", "https://www.example.com/form")

See alsoSubmitCaptchaToken

SolveHCaptchaDevTools, CDP, Stealth, Captcha and Office/Document Preview

Solve hCaptcha given a known siteKey, and get the token back.

Parameters: siteKey string, page URL string. Returns the token as a String.

Signaturetoken = m_lv.SolveHCaptcha(siteKey, pageUrl)
Registeredsupported Reg-Freesupported
VBA
Dim token As String
token = m_lv.SolveHCaptcha("SITE-KEY", "https://www.example.com/form")
VBA
Dim token As String
token = pool.SolveHCaptcha(idx, "SITE-KEY", "https://www.example.com/form")

See alsoSubmitCaptchaToken

SubmitCaptchaTokenDevTools, CDP, Stealth, Captcha and Office/Document Preview

Submit a solved CAPTCHA token to the page (e.g. a token obtained from SolveRecaptchaV2 or SolveHCaptcha).

Signaturem_lv.SubmitCaptchaToken token
Registeredsupported Reg-Freesupported
VBA
m_lv.SubmitCaptchaToken token
VBA
pool.SubmitCaptchaToken idx, token

See alsoSolveRecaptchaV2, SolveHCaptcha

Office Document Editing (embedded Word/Excel/PowerPoint)

All members in this group are Registered Only — confirmed both by the main API reference (which shows no Reg-Free examples for this group) and by explicit Mode: Registered Only tags on the auto-synced entries.

OpenOfficeDocumentDevTools, CDP, Stealth, Captcha and Office/Document Preview

Open and embed an Office document for editing.

Signaturem_lv.OpenOfficeDocument filePath
Registeredsupported Reg-Freenot available – use ShowDocumentPreview
VBA
m_lv.OpenOfficeDocument "C:\Documents\Report.docx"

Gotchas

  • Not available in the pool — the source states explicitly: "Not available in pool - use ShowDocumentPreview".
  • For Reg-Free document display, use ShowDocumentPreview / ShowDocumentPreviewInBrowserFrame instead; these show a preview, not an editable embedded document.

See alsoShowDocumentPreview, ShowDocumentPreviewInBrowserFrame

CloseOfficeDocumentDevTools, CDP, Stealth, Captcha and Office/Document Preview

Close the currently embedded Office document.

Signaturem_lv.CloseOfficeDocument
Registeredsupported Reg-Freenot available
VBA
m_lv.CloseOfficeDocument

SaveOfficeDocumentDevTools, CDP, Stealth, Captcha and Office/Document Preview

Save the embedded Office document.

Signaturem_lv.SaveOfficeDocument
Registeredsupported Reg-Freenot available
VBA
m_lv.SaveOfficeDocument

SaveOfficeDocumentAsDevTools, CDP, Stealth, Captcha and Office/Document Preview

Save the embedded Office document with a new filename.

Parameter: filePath.

Signaturem_lv.SaveOfficeDocumentAs filePath
Registeredsupported Reg-Freenot available
VBA
m_lv.SaveOfficeDocumentAs "C:\Documents\Report_v2.docx"

IsOfficeDocumentOpenDevTools, CDP, Stealth, Captcha and Office/Document Preview

Check if an Office document is currently embedded.

Type: Boolean. Read-only.

Signaturem_lv.IsOfficeDocumentOpen
Registeredsupported Reg-Freenot available
VBA
If m_lv.IsOfficeDocumentOpen Then
    ' ...
End If

OfficeDocumentPathDevTools, CDP, Stealth, Captcha and Office/Document Preview

Get the path of the currently embedded Office document.

Type: String. Read-only.

Signaturem_lv.OfficeDocumentPath
Registeredsupported Reg-Freenot available
VBA
Debug.Print "Path: " & m_lv.OfficeDocumentPath

OfficeDocumentTypeDevTools, CDP, Stealth, Captcha and Office/Document Preview

Get the type of the embedded document: Word, Excel, PowerPoint, or Unknown.

Type: String. Read-only.

Signaturem_lv.OfficeDocumentType
Registeredsupported Reg-Freenot available
VBA
Debug.Print "Type: " & m_lv.OfficeDocumentType

See alsoCurrentDocumentType

WordApplicationDevTools, CDP, Stealth, Captcha and Office/Document Preview

Get the Word.Application object for automation.

Type: Object. Read-only.

SignatureSet wdApp = m_lv.WordApplication
Registeredsupported Reg-Freenot available
VBA
Dim wdApp As Object
Set wdApp = m_lv.WordApplication

WordDocumentDevTools, CDP, Stealth, Captcha and Office/Document Preview

Get the active Word.Document object for automation.

Type: Object. Read-only.

SignatureSet wdDoc = m_lv.WordDocument
Registeredsupported Reg-Freenot available
VBA
Dim wdDoc As Object
Set wdDoc = m_lv.WordDocument

Generic Document Viewer (OpenDocument)

This is a separate, broader viewer than the Office-editing group above: it opens images, PDFs, videos, and Office docs, and is available in both modes.

OpenDocumentDevTools, CDP, Stealth, Captcha and Office/Document Preview

Open any document type (images, PDFs, videos, Office docs).

Parameters: filePath, documentType (Long; 0 = Auto per the source's inline comment — no other numeric values for this parameter are documented in the source).

Signaturem_lv.OpenDocument filePath, documentType
Registeredsupported Reg-Freesupported
VBA
m_lv.OpenDocument "C:\Photos\image.png", 0   ' 0=Auto
m_lv.OpenDocument "C:\Docs\report.pdf", 0
VBA
pool.OpenDocument idx, "C:\Photos\image.png", 0

Gotchas

  • The documentType parameter is a Long where 0 means Auto per the source's inline comment; no other numeric values for this parameter are documented in the source.

See alsoCurrentDocumentPath, CurrentDocumentType

CurrentDocumentPath / GetCurrentDocumentPathDevTools, CDP, Stealth, Captcha and Office/Document Preview

Get the file path of the currently open document (as opened via OpenDocument).

Signaturem_lv.CurrentDocumentPath
Registeredsupported Reg-Freesupported
VBA
Debug.Print m_lv.CurrentDocumentPath
VBA
Dim result As String
result = pool.GetCurrentDocumentPath(idx)

Gotchas

  • CurrentDocumentPath (property) is Registered Only; GetCurrentDocumentPath (method) is Reg-Free Only. This is not a contradiction: each mode simply exposes this value under a different member name, and no part of the source claims the other name works in the opposite mode.

See alsoOpenDocument, CurrentDocumentType

CurrentDocumentType / GetCurrentDocumentTypeDevTools, CDP, Stealth, Captcha and Office/Document Preview

Get the type of the currently open document.

Documented values (Registered property description): Image, PDF, Video, Audio, Text, Word, Excel, PowerPoint, Unknown. Note this list is broader than OfficeDocumentType's Word/Excel/PowerPoint/Unknown, since OpenDocument/CurrentDocumentType covers the generic viewer while OfficeDocumentType covers only the embedded-Office-editing path.

Signaturem_lv.CurrentDocumentType
Registeredsupported Reg-Freesupported
VBA
Debug.Print m_lv.CurrentDocumentType
VBA
Dim result As String
result = pool.GetCurrentDocumentType(idx)

Gotchas

  • CurrentDocumentType (property) is Registered Only; GetCurrentDocumentType (method) is Reg-Free Only — a per-mode naming split, same as CurrentDocumentPath/GetCurrentDocumentPath.

See alsoOpenDocument, CurrentDocumentPath, OfficeDocumentType

Document Preview (overlay, separate from WebView2)

ShowDocumentPreviewDevTools, CDP, Stealth, Captcha and Office/Document Preview

Show an Office document preview in a window handle.

Per the auto-synced description: "Completely separate from WebView2. Pass the window handle of a Frame control."

Signaturem_lv.ShowDocumentPreview filePath, hwndTarget
Registeredsupported Reg-Freesupported
VBA
m_lv.ShowDocumentPreview "C:\Docs\file.pdf", m_lv.EmbeddedParentHwnd
VBA
pool.ShowDocumentPreview idx, "C:\Docs\file.pdf"

Note

Mode difference, not a contradiction: both the main API reference and the auto-synced IDL reference agree on this asymmetry — Registered mode's ShowDocumentPreview requires a hwndTarget parameter that Reg-Free mode's ShowDocumentPreview does not take.

Gotchas

  • Registered mode takes filePath and a target window handle (hwndTarget); Reg-Free mode takes only filePath — no target window handle parameter. Both the main API reference and the auto-synced IDL reference agree on this asymmetry, and both state it is a mode difference, not a contradiction.
  • The Registered example's EmbeddedParentHwnd (which returns the embedded parent Frame's window handle) is documented in the embedding/window-management reference, not here.

See alsoEmbeddedParentHwnd, ShowDocumentPreviewInBrowserFrame, CloseDocumentPreview

ShowDocumentPreviewInBrowserFrameDevTools, CDP, Stealth, Captcha and Office/Document Preview

Show an Office document preview in the same Frame as WebView2.

Per the auto-synced description, this automatically hides WebView2.

Signaturem_lv.ShowDocumentPreviewInBrowserFrame filePath
Registeredsupported Reg-Freesupported
VBA
m_lv.ShowDocumentPreviewInBrowserFrame "C:\Docs\file.pdf"
VBA
pool.ShowDocumentPreviewInBrowserFrame idx, "C:\Docs\file.pdf"

Gotchas

  • The Reg-Free signature is documented only in the auto-synced IDL reference — the main API reference's Reg-Free example block for this group demonstrated only ShowDocumentPreview and CloseDocumentPreview, not this member, but does not state it is unavailable in Reg-Free.

See alsoShowDocumentPreview, CloseDocumentPreview

CloseDocumentPreviewDevTools, CDP, Stealth, Captcha and Office/Document Preview

Close any active document preview.

Signaturem_lv.CloseDocumentPreview
Registeredsupported Reg-Freesupported
VBA
m_lv.CloseDocumentPreview
VBA
pool.CloseDocumentPreview idx

See alsoShowDocumentPreview, ShowDocumentPreviewInBrowserFrame

Licensing

ActivateLicenseLicensing

Activate the license with a company name and a V1 activation string. If a key is not supplied in code, the 30-day Trial Period applies.

The key argument is an opaque V1 activation string. The runtime validates it and enforces any expiry timestamp it carries. Activation is in-memory only — no registry, no file system, no network call. Activation is session-only: the runtime does not persist activation across sessions/process restarts (does not persist across Access restarts). Call ActivateLicense from your Form_Load / UserForm_Initialize on every launch.

Signaturectrl.ActivateLicense companyName, activationKey
Registeredsupported Reg-Freesupported
VBA
m_lv.ActivateLicense "My Company", "V1|...|..."
Debug.Print "Status: " & m_lv.LicenseStatus
Debug.Print "Type: " & m_lv.LicenseType
Debug.Print "State: " & m_lv.LicenseState
Debug.Print "Days remaining: " & m_lv.TrialDaysRemaining
Debug.Print "Expiry: " & m_lv.LicenseExpiry
Debug.Print "Version: " & m_lv.LicenseVersion
Debug.Print "Info JSON: " & m_lv.GetLicenseInfo()
VBA
pool.ActivateLicense "My Company", "V1|...|..."
Debug.Print "Status: " & pool.LicenseStatus
Debug.Print "Type: " & pool.LicenseType
Debug.Print "State: " & pool.LicenseState
Debug.Print "Trial days: " & pool.TrialDaysRemaining
Debug.Print "Info JSON: " & pool.GetLicenseInfo()

Note

the Reg-Free usage example above is transcribed exactly as documented in the source, calling LicenseStatus/LicenseType/LicenseState/TrialDaysRemaining as plain properties on pool with no browserIndex/idx argument. Elsewhere in the source (the per-property reference entries below), the Reg-Free getters for these same members are documented as Get* methods that DO take a browserIndex argument (e.g. pool.GetLicenseStatus browserIndex, value). This is a genuine discrepancy in the source between the two documented forms — see the "CONTRADICTIONS" note in each property section below. ActivateLicense itself and GetLicenseInfo are consistently documented, in both places they appear, as not taking a browserIndex/idx argument in Reg-Free mode.

Gotchas

  • Recommended placement: put the activation key as a Const in a shared module — modLV2License.bas for Registered Mode (forms call EnsureLicensed m_lv in Form_Load), or modLV2Pool.bas for Reg-Free Mode (GetPool() activates automatically on the first call in the process).
  • Never paste the activation string into per-form code — rotating the key would then mean touching every form.
  • Never call ActivateLicense AFTER the first Navigate. The watermark may already have rendered.
  • Never call ActivateLicense inside WebViewReady / OnBrowserReady. By the time those fire, the navigation decision has already used the license state.

ActivateLicense is process-wide, not per-form and not per-browser:

  • ONE successful ActivateLicense call activates every LiteView2 browser created afterwards in the same Access (or Office) session.
  • The Reg-Free pool shares the activated license across every CreateInControl call automatically — you do not register the license per browser-index.
  • Activation does not persist across Access restarts. Each fresh process must call ActivateLicense once — that's what EnsureLicensed and GetPool handle for you.

Recommended pattern (already baked into the canonical templates): the activation key lives in a shared module, never duplicated across forms. Whichever form opens first in the process triggers the activation; every later form inherits the licensed state via the same shared module. You change the key once, in one file.

The shared-module activation IS idempotent. EnsureLicensed checks a flag and exits early on subsequent calls. GetPool only initialises once. So even if a form re-imports the helper or you accidentally call it twice, there's no harm.

LicenseStatusLicensing

Get license status as a string. Possible values: TRIAL, EXPIRED, PRO, ENTERPRISE, EVAL.

An EVAL key returns EVAL while unexpired, and reverts to EXPIRED once its expiry timestamp passes.

Signaturevalue = ctrl.LicenseStatus
Registeredsupported Reg-Freedocumented two ways
VBA
Dim value As String
value = ctrl.LicenseStatus
VBA
Dim value As String
pool.GetLicenseStatus idx, value

Gotchas

  • CONTRADICTION: the ActivateLicense usage example (see above) reads this same value in Reg-Free mode as a bare property — pool.LicenseStatus — with no index argument, rather than as pool.GetLicenseStatus idx, value. Both forms are presented verbatim as documented; the source does not reconcile them.

See alsoActivateLicense

LicenseTypeLicensing

Get license type as a lowercase string. Possible values: trial, eval, pro, enterprise, none.

The eval value indicates an active Extended Evaluation License (Section 2.3 of the EULA) issued at the Licensor's discretion to MVPs, educators, reviewers, and community contributors.

Signaturevalue = ctrl.LicenseType
Registeredsupported Reg-Freedocumented two ways
VBA
Dim value As String
value = ctrl.LicenseType
VBA
Dim value As String
pool.GetLicenseType idx, value

Gotchas

  • CONTRADICTION: the ActivateLicense usage example reads this value in Reg-Free mode as a bare property — pool.LicenseType — with no index argument. See the note under ActivateLicense above.

See alsoActivateLicense

LicenseStateLicensing

Current license state as enum (Valid, Trial, Expired, Invalid).

PRO, Enterprise, and Extended Evaluation (EVAL within expiry) all return Valid (value 0). Once an EVAL key passes its expiry timestamp, the state reverts to Expired (value 2). No new enum value is added at the LV2_LICENSE_STATE level for EVAL — it is folded into Valid while the key is unexpired.

Enum LV2_LICENSE_STATE values: 0=Valid, 1=Trial, 2=Expired, 3=Invalid

Signaturevalue = ctrl.LicenseState
Registeredsupported Reg-Freedocumented two ways
VBA
Dim value As LV2_LICENSE_STATE
value = ctrl.LicenseState
VBA
Dim value As LV2_LICENSE_STATE
pool.GetLicenseState idx, value

Gotchas

  • CONTRADICTION: the ActivateLicense usage example reads this value in Reg-Free mode as a bare property — pool.LicenseState — with no index argument. See the note under ActivateLicense above.

See alsoActivateLicense

LicenseExpiryLicensing

Get license expiry date as a DATE. Returns 0 for perpetual licenses (PRO, Enterprise) with no expiry.

For an Extended Evaluation (EVAL) license, returns the expiry timestamp encoded in the activation key.

Signaturevalue = ctrl.LicenseExpiry
Registeredsupported Reg-Freesupported
VBA
Dim value As Date
value = ctrl.LicenseExpiry
VBA
Dim value As Date
pool.GetLicenseExpiry idx, value

TrialDaysRemainingLicensing

Get trial days remaining. Returns 0 outside the 30-day Trial Period (e.g. when a paid license is active, when an Extended Evaluation is active, or when the trial has expired).

For Extended Evaluation keys, days-remaining is exposed via the daysRemaining field of GetLicenseInfo rather than via this property.

Signaturevalue = ctrl.TrialDaysRemaining
Registeredsupported Reg-Freedocumented two ways
VBA
Dim value As Long
value = ctrl.TrialDaysRemaining
VBA
Dim value As Long
pool.GetTrialDaysRemaining idx, value

Gotchas

  • CONTRADICTION: the ActivateLicense usage example reads this value in Reg-Free mode as a bare property — pool.TrialDaysRemaining — with no index argument. See the note under ActivateLicense above.

Note

Found via the auto-synced-section member search (this entry lives at line 9121 of the source, outside the two ranges that document the other license properties, though it is also referenced by name inside the ActivateLicense example at line 5463/5475).

See alsoActivateLicense, GetLicenseInfo

LicenseVersionLicensing

Get licensed version range.

Signaturevalue = ctrl.LicenseVersion
Registeredsupported Reg-Freesupported
VBA
Dim value As String
value = ctrl.LicenseVersion
VBA
Dim value As String
pool.GetLicenseVersion idx, value

GetLicenseInfoLicensing

Returns a small JSON document describing the current license. Read-only, informational only — does not include any credential material (no activation strings or signatures).

The first field is always "schemaVersion":1. Future informational fields will be additive.

Signatureinfo = ctrl.GetLicenseInfo()
Registeredsupported Reg-Freesupported

Example return value (Extended Evaluation):

JSON
{"schemaVersion":1,"tier":"EVAL","product":"LV2","company":"Crystal Long",
 "expiryUtc":"2027-05-18T23:59:59Z","isPerpetual":false,
 "daysRemaining":365,"state":"valid"}

Example return value (Trial):

JSON
{"schemaVersion":1,"tier":"Trial","product":"LV2","company":"",
 "expiryUtc":"2026-06-15T00:00:00Z","isPerpetual":false,
 "daysRemaining":12,"state":"trial"}

PRO / Enterprise (perpetual): "expiryUtc":null, "isPerpetual":true, "daysRemaining":null.

Use:

VBA
Dim info As String
info = m_lv.GetLicenseInfo()   ' Registered
info = pool.GetLicenseInfo()   ' Reg-Free
Debug.Print info

Note

unlike the other Reg-Free license accessors on this page (GetLicenseStatus, GetLicenseType, GetLicenseState, GetLicenseExpiry, GetLicenseVersion, GetTrialDaysRemaining), GetLicenseInfo in Reg-Free mode takes no browserIndex/idx argument — it is called directly on pool, exactly as documented in both places it appears in the source (the ActivateLicense example and this entry). This matches ActivateLicense's own pool-level (not per-browser-index) scope.

See alsoActivateLicense, LicenseStatus, LicenseType, LicenseState, LicenseExpiry, LicenseVersion, TrialDaysRemaining

Events (Registered Mode) and Reg-Free Callbacks

Overview

The two operating modes use two different notification models, and they are not interchangeable:

VBA
' Registered Mode — event sink declaration
Private WithEvents m_lv As LiteView2Lib.LiteView2Ctrl

Private Sub Form_Load()
    Set m_lv = Me.LiteView2Ctrl1.Object
End Sub

Reg-Free Readiness Callback

SetReadyCallbackReg-Free Readiness Callback

Registers a COM callback object/method to invoke when the browser is fully ready.

callbackObject must be STA-affine (a VBA form, VB6 class, etc.). Fires immediately if the browser is already ready at registration time. Fires exactly once per registration. Dispatched on the LiteView2 UI thread via PostMessage — never on WebView2 callback threads.

Signaturepool.SetReadyCallback idx, callbackObject, methodName
Registereduse WebViewReady event instead Reg-Freesupported
VBA
pool.SetReadyCallback idx, callbackObject, methodName
VBA
Private pool As Object
Private idx  As Long

Private Sub Form_Load()
    Set pool = GetPool()                                ' activates license internally
    idx = pool.CreateInControl("about:blank", Me.fraBrowser)
    pool.SetReadyCallback idx, Me, "OnBrowserReady"
End Sub

' Public — invoked by the pool by name, on the UI thread, when the browser is ready.
' No parameters.
Public Sub OnBrowserReady()
    pool.SetLocalContentRoot idx, CurrentProject.Path
    pool.SetAreHostObjectsAllowed idx, True
    pool.AddHostObjectToScript idx, "vba", Me
    pool.Navigate idx, "https://lv2.example/index.html"
End Sub

Gotchas

  • Migrating from the old Form_Timer + IsReady() polling pattern? Delete the timer. Replace the body of Form_Load with a single pool.SetReadyCallback idx, Me, "OnBrowserReady" call. Move whatever ran inside the If pool.IsReady(...) Then block into a public OnBrowserReady() sub on the same form. That is the entire migration.
  • No Registered-mode equivalent — Registered mode uses the WebViewReady event instead.

See alsoWebViewReady, IsReady, ClearReadyCallback

ClearReadyCallbackReg-Free Readiness Callback

Unregister the ready callback and allow re-registration.

Required in teardown: Form_Unload must call ClearReadyCallback before DestroyBrowserSync.

Signaturepool.ClearReadyCallback idx
Registerednot required — use Set m_lv = Nothing Reg-Freesupported
VBA
pool.ClearReadyCallback idx
VBA
Private Sub Form_Unload(Cancel As Integer)
    On Error Resume Next
    If Not pool Is Nothing And idx <> 0 Then
        pool.Stop idx                       ' halt any in-flight navigation
        pool.ClearReadyCallback idx         ' detach our callback so it can't fire after teardown
        pool.DestroyBrowserSync idx, 2000   ' synchronous browser teardown (max 2 s wait)
        idx = 0
    End If
    Set pool = Nothing
End Sub

Gotchas

  • Without this call, an async ready callback can fire back into VBA after the form's references are gone (Type mismatch / Object required errors).
  • Registered Mode has no equivalent requirement — it only needs Set m_lv = Nothing in Form_Close.

See alsoSetReadyCallback, DestroyBrowserSync

IsReadyReg-Free Readiness Callback

Check if WebView2 is ready.

Signaturectrl.IsReady() / pool.IsReady(idx)
Registeredsupported Reg-Freesupported
VBA
Dim result As Boolean
result = ctrl.IsReady()
VBA
Dim result As Boolean
result = pool.IsReady(idx)

Gotchas

  • In Reg-Free Mode, IsReady is the basis of the legacy Form_Timer + IsReady() polling pattern that SetReadyCallback supersedes — new code should use SetReadyCallback instead of polling IsReady.
  • Registered Mode code should similarly prefer the WebViewReady event over polling ctrl.IsReady().

See alsoSetReadyCallback, WebViewReady

Reg-Free VBA Callback Helpers (Pool-Only)

These control which VBA macros JavaScript is permitted to invoke via auto-dispatch, and let you register a specific JS-callable name bound to a specific VBA method — distinct from the readiness callback above.

SetAllowedVBAMacrosReg-Free VBA Callback Helpers

Set list of allowed VBA macros (comma-separated).

Signaturepool.SetAllowedVBAMacros idx, "CB_frmMyForm,CB_frmOther"
Registeredno direct equivalent Reg-Freesupported
VBA
pool.SetAllowedVBAMacros idx, "CB_frmMyForm,CB_frmOther"

See alsoClearAllowedVBAMacros, EnableAutoDispatch, RegisterVbaCallback

ClearAllowedVBAMacrosReg-Free VBA Callback Helpers

Clear allowed VBA macros list.

Signaturepool.ClearAllowedVBAMacros idx
Registeredno direct equivalent Reg-Freesupported
VBA
pool.ClearAllowedVBAMacros idx

See alsoSetAllowedVBAMacros

EnableAutoDispatchReg-Free VBA Callback Helpers

Enable auto-dispatch of HTML calls to VBA.

Signaturepool.EnableAutoDispatch idx, True
Registeredno direct equivalent Reg-Freesupported
VBA
pool.EnableAutoDispatch idx, True

See alsoIsAutoDispatchEnabled, SetAllowedVBAMacros

IsAutoDispatchEnabledReg-Free VBA Callback Helpers

Check if auto-dispatch is enabled.

Signatureresult = pool.IsAutoDispatchEnabled(idx)
Registeredno direct equivalent Reg-Freesupported
VBA
Dim result As Boolean
result = pool.IsAutoDispatchEnabled(idx)

See alsoEnableAutoDispatch

RegisterVbaCallbackReg-Free VBA Callback Helpers

Register VBA callback for JS to call.

Signaturepool.RegisterVbaCallback idx, "getData", callbackObj, "GetData"
Registeredno direct equivalent Reg-Freesupported
VBA
pool.RegisterVbaCallback idx, "getData", callbackObj, "GetData"

See alsoUnregisterVbaCallback, SetAllowedVBAMacros

UnregisterVbaCallbackReg-Free VBA Callback Helpers

Unregister VBA callback.

Signaturepool.UnregisterVbaCallback idx
Registeredno direct equivalent Reg-Freesupported
VBA
pool.UnregisterVbaCallback idx

See alsoRegisterVbaCallback

Events (Registered Mode Only)

Note

Events fire on ILiteView2Ctrl only — the ActiveX (registered) interface. Reg-Free mode uses callbacks (SetReadyCallback/ClearReadyCallback, SetWebMessageCallback) instead of events.

To handle events in VBA, declare the control with WithEvents:

VBA
Private WithEvents m_lv As LiteView2Lib.LiteView2Ctrl

Private Sub Form_Load()
    Set m_lv = Me.LiteView2Ctrl1.Object
End Sub

Then implement handlers as Private Sub m_lv_<EventName>(<args>). Or skip WithEvents and use event procedures named after the control (LiteView2Ctrl1_WebViewReady), as the Part I templates do. Use one style per form: a handler named after a variable that is not declared WithEvents never runs, and no error is shown.

Coverage: All 63 events from _DLiteView2CtrlEvents (DISPIDs 1-48, 60-64, 600-609).

Hex variants

NavigationCompletedHex, ContentLoadingHex, DownloadStartingHex, DownloadProgressChangedHex, DownloadCompletedHex fire only when the EventsUseHexadecimal property is True. They carry the same payload as the base event but with LONG values converted to hex BSTRs — a VB6 workaround for values larger than Long.MaxValue. In typical VBA/Access usage, ignore them and handle the base event instead.

Every event below is Registered Mode only; the mode tag is omitted per-event to avoid repetition.

Startup & Navigation Events

WebViewReadyStartup & Navigation Events

Fired when WebView2 initialization is complete (DISPID 48).

Set up and navigate here (SetLocalContentRoot, AreHostObjectsAllowed, AddHostObjectToScript, Navigate). Calls that wait for the browser fail here at once with &H80040203: read or change the page in NavigationCompleted. Register document scripts and EnableLvFacade earlier, in Form_Load.

SignaturePrivate Sub m_lv_WebViewReady()
Registeredsupported Reg-Freeuse SetReadyCallback instead
VBA
Private Sub m_lv_WebViewReady()
    m_lv.SetLocalContentRoot CurrentProject.Path & "\html"
    m_lv.Navigate "https://lv2.example/index.html"
End Sub

See alsoSetReadyCallback, IsReady

SourceChangedStartup & Navigation Events

Fired when the URL changes (DISPID 6).

SignaturePrivate Sub m_lv_SourceChanged(ByVal url As String)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_SourceChanged(ByVal url As String)
    Me.txtUrl = url
End Sub

HistoryChangedStartup & Navigation Events

Fired when browser history changes (back/forward availability) (DISPID 25).

SignaturePrivate Sub m_lv_HistoryChanged()
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_HistoryChanged()
    Me.btnBack.Enabled = m_lv.CanGoBack
    Me.btnForward.Enabled = m_lv.CanGoForward
End Sub

DOMContentLoadedStartup & Navigation Events

Fired when DOM content has finished loading (the DOMContentLoaded event), before images/scripts finish (DISPID 23).

SignaturePrivate Sub m_lv_DOMContentLoaded(ByVal navigationId As String)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_DOMContentLoaded(ByVal navigationId As String)
    Debug.Print "DOM ready, nav ID: " & navigationId
End Sub

ContentLoadingStartup & Navigation Events

Fired when content starts loading (DISPID 24).

SignaturePrivate Sub m_lv_ContentLoading(ByVal navigationId As String, ByVal isErrorPage As Boolean)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_ContentLoading(ByVal navigationId As String, ByVal isErrorPage As Boolean)
    Debug.Print "Loading... Error page: " & isErrorPage
End Sub

See alsoContentLoadingHex

ContentLoadingHexStartup & Navigation Events

Fired when EventsUseHexadecimal = True: content loading with NavigationId as BSTR hex (VB6 Int64 workaround) (DISPID 61).

SignaturePrivate Sub m_lv_ContentLoadingHex(ByVal navigationIdHex As String, ByVal isErrorPage As Boolean)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_ContentLoadingHex(ByVal navigationIdHex As String, ByVal isErrorPage As Boolean)
    Debug.Print "Loading nav: " & navigationIdHex
End Sub

Gotchas

  • Only fires when EventsUseHexadecimal is True; carries the same payload as ContentLoading with the NavigationId as a hex BSTR instead of a Long. See the Hex variants note above.

See alsoContentLoading

Messaging & Document Events

WebMessageReceivedMessaging & Document Events

Fired when JavaScript calls chrome.webview.postMessage(...) (DISPID 3).

SignaturePrivate Sub m_lv_WebMessageReceived(ByVal message As String, ByVal source As String)
Registeredsupported Reg-Freeuse SetWebMessageCallback instead
VBA
Private Sub m_lv_WebMessageReceived(ByVal message As String, ByVal source As String)
    If InStr(message, """action"":""save""") > 0 Then
        HandleSave message
    ElseIf InStr(message, """action"":""refresh""") > 0 Then
        RefreshData
    End If
End Sub

Gotchas

  • Note: JsonGetValue and the other JSON helpers never talk to the browser. They are safe in any handler, including WebMessageReceived.

See alsoSetWebMessageCallback

DocumentTitleChangedMessaging & Document Events

Fired when the document title changes (DISPID 4).

SignaturePrivate Sub m_lv_DocumentTitleChanged(ByVal title As String)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_DocumentTitleChanged(ByVal title As String)
    Me.Caption = title
End Sub

FaviconChangedMessaging & Document Events

Fired when the favicon of the current document changes (DISPID 600).

SignaturePrivate Sub m_lv_FaviconChanged(ByVal faviconUri As String)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_FaviconChanged(ByVal faviconUri As String)
    Debug.Print "Favicon: " & faviconUri
End Sub

StatusBarTextChangedMessaging & Document Events

Fired when status bar text changes (DISPID 29).

SignaturePrivate Sub m_lv_StatusBarTextChanged(ByVal statusText As String)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_StatusBarTextChanged(ByVal statusText As String)
    Me.lblStatus = statusText
End Sub

Window & Popup Events

NewWindowRequestedWindow & Popup Events

Fired when a popup or new window is requested (DISPID 5).

Set Cancel = True to block it.

SignaturePrivate Sub m_lv_NewWindowRequested(ByVal url As String, ByRef Cancel As Boolean)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_NewWindowRequested(ByVal url As String, ByRef Cancel As Boolean)
    Cancel = True   ' Block popups
    m_lv.Navigate url  ' Navigate in same window instead
End Sub

WindowCloseRequestedWindow & Popup Events

Fired when window.close() is called from JavaScript (DISPID 27).

SignaturePrivate Sub m_lv_WindowCloseRequested()
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_WindowCloseRequested()
    DoCmd.Close acForm, Me.Name
End Sub

MoveFocusRequestedWindow & Popup Events

Fired when a focus move is requested (e.g. Tab) (DISPID 604).

Params: reason (LV2_FOCUS_REASON), Handled.

SignaturePrivate Sub m_lv_MoveFocusRequested(ByVal reason As Long, ByRef Handled As Boolean)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_MoveFocusRequested(ByVal reason As Long, ByRef Handled As Boolean)
    Debug.Print "Focus move requested, reason: " & reason
End Sub

Dialogs & UI Prompts

ScriptDialogOpeningDialogs & UI Prompts

Fired when a JS alert/confirm/prompt dialog opens (DISPID 7).

Notification only — no Cancel/handled output parameter.

SignaturePrivate Sub m_lv_ScriptDialogOpening(ByVal message As String, ByVal dialogType As Long)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_ScriptDialogOpening(ByVal message As String, ByVal dialogType As Long)
    Debug.Print "Dialog type " & dialogType & ": " & message
End Sub

SaveAsUIShowingDialogs & UI Prompts

Fired when the Save As dialog is about to show (DISPID 607).

SignaturePrivate Sub m_lv_SaveAsUIShowing(ByRef Cancel As Boolean)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_SaveAsUIShowing(ByRef Cancel As Boolean)
    Cancel = True   ' Block Save As
End Sub

ContextMenuRequestedDialogs & UI Prompts

Fired when a context menu is requested (right-click) (DISPID 601).

args (Object) exposes: LocationX, LocationY, PageUri, LinkUri, Handled.

SignaturePrivate Sub m_lv_ContextMenuRequested(ByVal args As Object)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_ContextMenuRequested(ByVal args As Object)
    Debug.Print "Context menu requested"
End Sub

Export & DevTools Completion Events

PrintToPdfCompletedExport & DevTools Completion Events

Fired after a print-to-PDF operation completes (DISPID 8).

SignaturePrivate Sub m_lv_PrintToPdfCompleted(ByVal filePath As String, ByVal success As Boolean)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_PrintToPdfCompleted(ByVal filePath As String, ByVal success As Boolean)
    If success Then Application.FollowHyperlink filePath
End Sub

Gotchas

  • Async results like this one have no Reg-Free equivalent: check the output file on the next user action, or expose a host object whose method JavaScript calls to signal completion.

CaptureScreenshotCompletedExport & DevTools Completion Events

Fired after a screenshot capture operation completes (DISPID 9).

SignaturePrivate Sub m_lv_CaptureScreenshotCompleted(ByVal filePath As String, ByVal success As Boolean)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_CaptureScreenshotCompleted(ByVal filePath As String, ByVal success As Boolean)
    If success Then Debug.Print "Screenshot saved: " & filePath
End Sub

Gotchas

  • Async results like this one have no Reg-Free equivalent: check the output file on the next user action, or expose a host object whose method JavaScript calls to signal completion.

DevToolsProtocolEventReceivedExport & DevTools Completion Events

Raised when a CDP event you subscribed to with AddDevToolsProtocolEventHandler occurs (DISPID 10). Some domains must be enabled first, e.g. CallDevToolsProtocolMethod "Network.enable", "{}". eventName is the CDP event name and eventDataJson the payload as JSON.

The event is raised a moment after WebView2's callback has returned, in arrival order, so synchronous calls (CallDevToolsProtocolMethod, ExecuteScript) work inside the handler. An event still waiting when you remove its subscription is not raised. Registered mode only: the Reg-Free pool accepts the subscription but raises no events.

SignaturePrivate Sub m_lv_DevToolsProtocolEventReceived(ByVal eventName As String, ByVal eventDataJson As String)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_DevToolsProtocolEventReceived(ByVal eventName As String, ByVal eventDataJson As String)
    Debug.Print eventName & ": " & eventDataJson
End Sub

Download Events

DownloadStartingDownload Events

Fired when a download is about to begin (DISPID 11).

Set resultFilePath to redirect the save location, or set Cancel = True to block it.

SignaturePrivate Sub m_lv_DownloadStarting(ByVal url As String, ByVal suggestedFileName As String, ByVal totalBytes As Long, ByVal mimeType As String, ByRef Cancel As Boolean, ByRef resultFilePath As String)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_DownloadStarting(ByVal url As String, ByVal suggestedFileName As String, _
    ByVal totalBytes As Long, ByVal mimeType As String, _
    ByRef Cancel As Boolean, ByRef resultFilePath As String)
    resultFilePath = Environ("USERPROFILE") & "\Desktop\" & suggestedFileName
End Sub

See alsoDownloadStartingHex

DownloadStartingHexDownload Events

Fired when EventsUseHexadecimal = True: download starting with totalBytes as a BSTR hex string (DISPID 62).

SignaturePrivate Sub m_lv_DownloadStartingHex(ByVal url As String, ByVal suggestedFileName As String, ByVal totalBytesHex As String, ByVal mimeType As String, ByRef Cancel As Boolean, ByRef resultFilePath As String)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_DownloadStartingHex(ByVal url As String, ByVal suggestedFileName As String, _
    ByVal totalBytesHex As String, ByVal mimeType As String, _
    ByRef Cancel As Boolean, ByRef resultFilePath As String)
    Debug.Print "Size (hex): " & totalBytesHex
End Sub

Gotchas

  • Only fires when EventsUseHexadecimal is True; carries the same payload as DownloadStarting with totalBytes as a hex BSTR instead of a Long. See the Hex variants note above.

See alsoDownloadStarting

DownloadProgressChangedDownload Events

Fired during download progress (DISPID 12).

SignaturePrivate Sub m_lv_DownloadProgressChanged(ByVal downloadId As Long, ByVal bytesReceived As Long, ByVal totalBytes As Long, ByVal state As Long)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_DownloadProgressChanged(ByVal downloadId As Long, ByVal bytesReceived As Long, _
    ByVal totalBytes As Long, ByVal state As Long)
    If totalBytes > 0 Then
        Debug.Print "Progress: " & Int(bytesReceived / totalBytes * 100) & "%"
    End If
End Sub

See alsoDownloadProgressChangedHex

DownloadProgressChangedHexDownload Events

Fired when EventsUseHexadecimal = True: download progress with downloadId/bytes/total as BSTR hex (DISPID 63).

SignaturePrivate Sub m_lv_DownloadProgressChangedHex(ByVal downloadIdHex As String, ByVal bytesReceivedHex As String, ByVal totalBytesHex As String, ByVal state As Long)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_DownloadProgressChangedHex(ByVal downloadIdHex As String, ByVal bytesReceivedHex As String, _
    ByVal totalBytesHex As String, ByVal state As Long)
    Debug.Print "Download " & downloadIdHex & " state: " & state
End Sub

Gotchas

  • Only fires when EventsUseHexadecimal is True; carries the same payload as DownloadProgressChanged with downloadId/bytes/total as hex BSTRs instead of Longs. See the Hex variants note above.

See alsoDownloadProgressChanged

DownloadCompletedDownload Events

Fired when a download completes or fails (DISPID 13).

SignaturePrivate Sub m_lv_DownloadCompleted(ByVal downloadId As Long, ByVal filePath As String, ByVal success As Boolean, ByVal interruptReason As Long)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_DownloadCompleted(ByVal downloadId As Long, ByVal filePath As String, _
    ByVal success As Boolean, ByVal interruptReason As Long)
    If success Then
        MsgBox "Downloaded: " & filePath
    Else
        Debug.Print "Download failed, reason: " & interruptReason
    End If
End Sub

See alsoDownloadCompletedHex

DownloadCompletedHexDownload Events

Fired when EventsUseHexadecimal = True: download completed with downloadId as a BSTR hex string (DISPID 64).

SignaturePrivate Sub m_lv_DownloadCompletedHex(ByVal downloadIdHex As String, ByVal filePath As String, ByVal success As Boolean, ByVal interruptReason As Long)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_DownloadCompletedHex(ByVal downloadIdHex As String, ByVal filePath As String, _
    ByVal success As Boolean, ByVal interruptReason As Long)
    Debug.Print "Download " & downloadIdHex & " done: " & success
End Sub

Gotchas

  • Only fires when EventsUseHexadecimal is True; carries the same payload as DownloadCompleted with downloadId as a hex BSTR instead of a Long. See the Hex variants note above.

See alsoDownloadCompleted

IsDefaultDownloadDialogOpenChangedDownload Events

Fired when the default download dialog open state changes (DISPID 606).

SignaturePrivate Sub m_lv_IsDefaultDownloadDialogOpenChanged()
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_IsDefaultDownloadDialogOpenChanged()
    Debug.Print "Download dialog state changed"
End Sub

Authentication & Security Events

BasicAuthenticationRequestedAuthentication & Security Events

Fired when the server requests HTTP Basic Authentication (DISPID 14).

SignaturePrivate Sub m_lv_BasicAuthenticationRequested(ByVal uri As String, ByVal challenge As String, ByRef username As String, ByRef password As String, ByRef handled As Boolean)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_BasicAuthenticationRequested(ByVal uri As String, ByVal challenge As String, _
    ByRef username As String, ByRef password As String, ByRef handled As Boolean)
    username = InputBox("Username for " & uri)
    password = InputBox("Password")
    handled = True
End Sub

ClientCertificateRequestedAuthentication & Security Events

Fired when the server requests a client certificate (DISPID 15).

SignaturePrivate Sub m_lv_ClientCertificateRequested(ByVal uri As String, ByRef handled As Boolean)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_ClientCertificateRequested(ByVal uri As String, ByRef handled As Boolean)
    Debug.Print "Client cert requested for: " & uri
    handled = False  ' Let browser handle
End Sub

ServerCertificateErrorDetectedAuthentication & Security Events

Fired when an SSL/TLS certificate error is detected (DISPID 16).

action: 0 = deny, 1 = allow.

SignaturePrivate Sub m_lv_ServerCertificateErrorDetected(ByVal uri As String, ByVal errorStatus As Long, ByVal certificateSubject As String, ByRef action As Long)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_ServerCertificateErrorDetected(ByVal uri As String, ByVal errorStatus As Long, _
    ByVal certificateSubject As String, ByRef action As Long)
    Debug.Print "Cert error at " & uri & ": " & certificateSubject
    ' action = 0 to deny, 1 to allow
End Sub

SaveFileSecurityCheckStartingAuthentication & Security Events

Fired when a file-save security check starts (DISPID 609).

SignaturePrivate Sub m_lv_SaveFileSecurityCheckStarting(ByVal filePath As String, ByRef Cancel As Boolean)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_SaveFileSecurityCheckStarting(ByVal filePath As String, ByRef Cancel As Boolean)
    Debug.Print "Security check for: " & filePath
End Sub

ScreenCaptureStartingAuthentication & Security Events

Fired when screen capture is about to start (e.g. getDisplayMedia) (DISPID 608).

SignaturePrivate Sub m_lv_ScreenCaptureStarting(ByRef Cancel As Boolean)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_ScreenCaptureStarting(ByRef Cancel As Boolean)
    Cancel = True   ' Block screen capture
End Sub

Process Events

ProcessFailedProcess Events

Fired when the browser process fails or crashes (DISPID 17).

reasonMessage and frameInfo are populated from the SDK when available.

SignaturePrivate Sub m_lv_ProcessFailed(ByVal processKind As Long, ByVal reason As Long, ByVal exitCode As Long, ByVal reasonMessage As String, ByVal frameInfo As String)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_ProcessFailed(ByVal processKind As Long, ByVal reason As Long, _
    ByVal exitCode As Long, ByVal reasonMessage As String, ByVal frameInfo As String)
    Debug.Print "Process failed: " & reasonMessage
End Sub

CreateWebViewCompletedProcess Events

Fired when WebView2 controller creation finishes (DISPID 34).

SignaturePrivate Sub m_lv_CreateWebViewCompleted(ByVal hResult As Long, ByVal success As Boolean)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_CreateWebViewCompleted(ByVal hResult As Long, ByVal success As Boolean)
    If Not success Then
        MsgBox "WebView2 creation failed: " & Hex(hResult)
    End If
End Sub

BrowserProcessExitedProcess Events

Fired when the browser process exits (from Environment) (DISPID 605).

SignaturePrivate Sub m_lv_BrowserProcessExited(ByVal exitKind As Long, ByVal processId As Long)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_BrowserProcessExited(ByVal exitKind As Long, ByVal processId As Long)
    Debug.Print "Browser process " & processId & " exited, kind: " & exitKind
End Sub

Web Resource Events

WebResourceRequestedWeb Resource Events

Fired when a filtered web resource is requested (DISPID 18).

Set Cancel = True to block it.

SignaturePrivate Sub m_lv_WebResourceRequested(ByVal uri As String, ByVal method As String, ByVal resourceContext As Long, ByRef Cancel As Boolean)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_WebResourceRequested(ByVal uri As String, ByVal method As String, _
    ByVal resourceContext As Long, ByRef Cancel As Boolean)
    If InStr(uri, "ads") > 0 Then Cancel = True
End Sub

WebResourceResponseReceivedWeb Resource Events

Fired when a web resource response is received (DISPID 19).

SignaturePrivate Sub m_lv_WebResourceResponseReceived(ByVal uri As String, ByVal statusCode As Long, ByVal reasonPhrase As String)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_WebResourceResponseReceived(ByVal uri As String, ByVal statusCode As Long, _
    ByVal reasonPhrase As String)
    Debug.Print statusCode & " " & reasonPhrase & " - " & uri
End Sub

Find Events

FindMatchCountChangedFind Events

Fired when the find match count changes (DISPID 20).

SignaturePrivate Sub m_lv_FindMatchCountChanged(ByVal matchCount As Long)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_FindMatchCountChanged(ByVal matchCount As Long)
    Me.lblMatches = matchCount & " matches"
End Sub

FindActiveMatchChangedFind Events

Fired when the active match index changes (DISPID 21).

SignaturePrivate Sub m_lv_FindActiveMatchChanged(ByVal activeMatchIndex As Long)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_FindActiveMatchChanged(ByVal activeMatchIndex As Long)
    Me.lblMatch = "Match " & activeMatchIndex & " of " & m_lv.FindMatchCount
End Sub

FindCompletedFind Events

Fired when a find session completes (DISPID 22).

SignaturePrivate Sub m_lv_FindCompleted(ByVal matchCount As Long)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_FindCompleted(ByVal matchCount As Long)
    Debug.Print "Find completed: " & matchCount & " matches"
End Sub

Zoom, Fullscreen & Media State Events

ZoomFactorChangedZoom, Fullscreen & Media State Events

Fired when the zoom factor changes (DISPID 26).

SignaturePrivate Sub m_lv_ZoomFactorChanged(ByVal newZoomFactor As Double)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_ZoomFactorChanged(ByVal newZoomFactor As Double)
    Me.lblZoom = Int(newZoomFactor * 100) & "%"
End Sub

ContainsFullScreenElementChangedZoom, Fullscreen & Media State Events

Fired when the fullscreen element state changes (video fullscreen, etc.) (DISPID 28).

SignaturePrivate Sub m_lv_ContainsFullScreenElementChanged(ByVal containsFullScreenElement As Boolean)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_ContainsFullScreenElementChanged(ByVal containsFullScreenElement As Boolean)
    If containsFullScreenElement Then
        ' Enter fullscreen mode
    End If
End Sub

IsMutedChangedZoom, Fullscreen & Media State Events

Fired when the mute state of the document changes (DISPID 31).

SignaturePrivate Sub m_lv_IsMutedChanged(ByVal isMuted As Boolean)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_IsMutedChanged(ByVal isMuted As Boolean)
    Debug.Print "Muted: " & isMuted
End Sub

IsDocumentPlayingAudioChangedZoom, Fullscreen & Media State Events

Fired when audio playback status changes (DISPID 32).

SignaturePrivate Sub m_lv_IsDocumentPlayingAudioChanged(ByVal isPlayingAudio As Boolean)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_IsDocumentPlayingAudioChanged(ByVal isPlayingAudio As Boolean)
    Debug.Print "Playing audio: " & isPlayingAudio
End Sub

Keyboard & Focus Events (Control-Level)

AcceleratorKeyPressedKeyboard & Focus Events (Control-Level)

Fired when an accelerator key (keyboard shortcut) is pressed (DISPID 33).

SignaturePrivate Sub m_lv_AcceleratorKeyPressed(ByVal keyEventKind As Long, ByVal virtualKey As Long, ByVal keyEventLParam As Long, ByRef handled As Boolean)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_AcceleratorKeyPressed(ByVal keyEventKind As Long, ByVal virtualKey As Long, _
    ByVal keyEventLParam As Long, ByRef handled As Boolean)
    If virtualKey = vbKeyF5 Then
        handled = True  ' Suppress F5 refresh
    End If
End Sub

ClickKeyboard & Focus Events (Control-Level)

Fired when the control is clicked (DISPID 39).

Known issue in 1.0.1.0

Click, DblClick, KeyPress, MouseEnter and MouseLeave are raised only for input that reaches the control's own window. Over the web content the input goes to WebView2's window, so these events do not fire there. To react to clicks or keys in the page, handle them in JavaScript and send chrome.webview.postMessage(...) to WebMessageReceived.

SignaturePrivate Sub m_lv_Click()
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_Click()
    Debug.Print "Control clicked"
End Sub

DblClickKeyboard & Focus Events (Control-Level)

Fired when the control is double-clicked (DISPID 40). Known issue in 1.0.1.0: not raised for input over the web content — see Click.

SignaturePrivate Sub m_lv_DblClick()
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_DblClick()
    Debug.Print "Control double-clicked"
End Sub

KeyPressKeyboard & Focus Events (Control-Level)

Fired when a key is pressed while the control has focus (DISPID 41). Known issue in 1.0.1.0: not raised for input over the web content — see Click.

SignaturePrivate Sub m_lv_KeyPress(ByVal keyCode As Long)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_KeyPress(ByVal keyCode As Long)
    Debug.Print "Key pressed: " & keyCode & " (" & Chr(keyCode) & ")"
End Sub

MouseEnterKeyboard & Focus Events (Control-Level)

Fired when the mouse enters the control area (DISPID 42). Known issue in 1.0.1.0: not raised for input over the web content — see Click.

SignaturePrivate Sub m_lv_MouseEnter()
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_MouseEnter()
    Debug.Print "Mouse entered"
End Sub

MouseLeaveKeyboard & Focus Events (Control-Level)

Fired when the mouse leaves the control area (DISPID 43). Known issue in 1.0.1.0: not raised for input over the web content — see Click.

SignaturePrivate Sub m_lv_MouseLeave()
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_MouseLeave()
    Debug.Print "Mouse left"
End Sub

BrowserGotFocusKeyboard & Focus Events (Control-Level)

Fired when the web content receives focus (DISPID 44).

BrowserGotFocus / BrowserLostFocus (DISPID 44 / 45). They were renamed from GotFocus / LostFocus, which the VB6 runtime reserves for its own extender events.

Known issue in 1.0.1.0

LiteView2 does not raise these two events yet. A handler named …_GotFocus binds, at most, to the host's own focus event, not to LiteView2's.

SignaturePrivate Sub m_lv_BrowserGotFocus()
Registerednot raised in 1.0.1.0 Reg-Freeno direct equivalent
VBA
Private Sub m_lv_BrowserGotFocus()
    Debug.Print "Got focus"
End Sub

BrowserLostFocusKeyboard & Focus Events (Control-Level)

Fired when the web content loses focus (DISPID 45). Known issue in 1.0.1.0: not raised yet — see BrowserGotFocus.

SignaturePrivate Sub m_lv_BrowserLostFocus()
Registerednot raised in 1.0.1.0 Reg-Freeno direct equivalent
VBA
Private Sub m_lv_BrowserLostFocus()
    Debug.Print "Lost focus"
End Sub

Permission Events

PermissionRequestedPermission Events

Fired when a permission is requested (camera, microphone, geolocation, etc.) (DISPID 30).

state: 0 = Default, 1 = Allow, 2 = Deny.

SignaturePrivate Sub m_lv_PermissionRequested(ByVal uri As String, ByVal permissionKind As Long, ByVal isUserInitiated As Boolean, ByRef state As Long)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_PermissionRequested(ByVal uri As String, ByVal permissionKind As Long, _
    ByVal isUserInitiated As Boolean, ByRef state As Long)
    state = 1  ' Allow (0=Default, 1=Allow, 2=Deny)
End Sub

Frame (iFrame) Events

FrameCreatedFrame (iFrame) Events

Fired when a new iFrame is created (DISPID 35).

SignaturePrivate Sub m_lv_FrameCreated(ByVal frameName As String, ByVal frameId As String)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_FrameCreated(ByVal frameName As String, ByVal frameId As String)
    Debug.Print "Frame created: " & frameName & " (" & frameId & ")"
End Sub

FrameNavigationStartingFrame (iFrame) Events

Fired when an iFrame starts navigation (DISPID 36).

SignaturePrivate Sub m_lv_FrameNavigationStarting(ByVal frameId As String, ByVal uri As String, ByVal isRedirected As Boolean, ByRef Cancel As Boolean)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_FrameNavigationStarting(ByVal frameId As String, ByVal uri As String, _
    ByVal isRedirected As Boolean, ByRef Cancel As Boolean)
    Debug.Print "Frame " & frameId & " navigating to: " & uri
End Sub

FrameNavigationCompletedFrame (iFrame) Events

Fired when an iFrame completes navigation (DISPID 37).

SignaturePrivate Sub m_lv_FrameNavigationCompleted(ByVal frameId As String, ByVal uri As String, ByVal success As Boolean, ByVal webErrorStatus As Long)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_FrameNavigationCompleted(ByVal frameId As String, ByVal uri As String, _
    ByVal success As Boolean, ByVal webErrorStatus As Long)
    Debug.Print "Frame " & frameId & " loaded: " & success
End Sub

FrameDestroyedFrame (iFrame) Events

Fired when an iFrame is destroyed (DISPID 38).

SignaturePrivate Sub m_lv_FrameDestroyed(ByVal frameId As String)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_FrameDestroyed(ByVal frameId As String)
    Debug.Print "Frame destroyed: " & frameId
End Sub

CAPTCHA Events

CaptchaDetectedCAPTCHA Events

Fired when a CAPTCHA is detected on the page (DISPID 46).

SignaturePrivate Sub m_lv_CaptchaDetected(ByVal captchaType As String, ByVal siteKey As String, ByVal pageUrl As String)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_CaptchaDetected(ByVal captchaType As String, ByVal siteKey As String, _
    ByVal pageUrl As String)
    Debug.Print "CAPTCHA found: " & captchaType & " key=" & siteKey
End Sub

See alsoCaptchaSolved

CaptchaSolvedCAPTCHA Events

Fired when CAPTCHA solving completes (DISPID 47).

SignaturePrivate Sub m_lv_CaptchaSolved(ByVal token As String, ByVal success As Boolean)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_CaptchaSolved(ByVal token As String, ByVal success As Boolean)
    If success Then
        Debug.Print "CAPTCHA solved, token: " & Left(token, 20) & "..."
    End If
End Sub

See alsoCaptchaDetected

External Navigation & Notification Events

LaunchingExternalUriSchemeExternal Navigation & Notification Events

Fired when navigation to an external URI scheme is requested (e.g. mailto:) (DISPID 602).

SignaturePrivate Sub m_lv_LaunchingExternalUriScheme(ByVal uri As String, ByRef Cancel As Boolean)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_LaunchingExternalUriScheme(ByVal uri As String, ByRef Cancel As Boolean)
    If Left(uri, 7) = "mailto:" Then
        Debug.Print "Email link: " & uri
    End If
End Sub

NotificationReceivedExternal Navigation & Notification Events

Fired when a web notification is received from the document (DISPID 603).

SignaturePrivate Sub m_lv_NotificationReceived(ByVal notification As String)
Registeredsupported Reg-Freeno direct equivalent
VBA
Private Sub m_lv_NotificationReceived(ByVal notification As String)
    Debug.Print "Notification: " & notification
End Sub

Enums Reference

This category documents every enumerated type defined by LiteView2, as listed in the source ENUMS REFERENCE table. Each enum is a Long-valued type used as a property/method return value, a property/method input parameter, or an event parameter elsewhere in the API. Where an enum's use in a specific member is confirmed elsewhere in this document, that member's name, mode, and a short signature are cross-referenced below; the full documentation for that member (description, all parameters, cautions) lives in its own category (Properties Reference / Methods Reference / Events Reference), not here.

Canonical variables used in signatures below: m_lv (Registered, As LiteView2Lib.LiteView2Ctrl), pool (Reg-Free, As Object), idx/browserIndex (Reg-Free browser index, As Long).

LV2_COLOR_SCHEMEEnums Reference

Color scheme preference.

Confirmed consuming member: GetPreferredColorScheme — Get preferred color scheme for browser profile.

Values0 = Auto, 1 = Light, 2 = Dark
Registeredno confirmed consuming member found Reg-Freesupported
VBA
Dim result As LV2_COLOR_SCHEME
result = pool.GetPreferredColorScheme(idx)

Gotchas

  • No Registered-mode member referencing this enum was found within the Additional API Reference (lines 6401-9204) or Events (lines 9205-9923) sections.

See alsoGetPreferredColorScheme

LV2_PRINT_ORIENTATIONEnums Reference

Print orientation.

Values0 = Portrait, 1 = Landscape

Gotchas

  • No consuming member referencing this enum by name was found within the Additional API Reference (6401-9204) or Events (9205-9923) sections.

LV2_POPUP_MODEEnums Reference

Popup handling mode.

Confirmed consuming member: GetPopupMode — Get popup mode.

Values0 = Allow, 1 = Block, 2 = SameWindow
Registeredno confirmed consuming member found Reg-Freesupported
VBA
Dim result As LV2_POPUP_MODE
result = pool.GetPopupMode(idx)

Gotchas

  • No Registered-mode member referencing this enum was found within the searched sections.
  • A related boolean member, GetOpenPopupsInSameWindow (Reg-Free Only, returns Boolean), was found adjacent to GetPopupMode in the source but is a separate, non-enum-typed member and belongs to its own category entry, not this one.

See alsoGetPopupMode, GetOpenPopupsInSameWindow

LV2_LICENSE_STATEEnums Reference

Current license state.

Confirmed consuming member: LicenseState (Property).

Values0 = Valid, 1 = Trial, 2 = Expired, 3 = Invalid
Registeredsupported Reg-Freesupported
VBA
' Registered
Dim value As LV2_LICENSE_STATE
value = m_lv.LicenseState
VBA
' Reg-Free
Dim value As LV2_LICENSE_STATE
pool.GetLicenseState idx, value

Caution

This note is drawn from the LicenseState property entry: PRO, Enterprise, and Extended Evaluation (EVAL, within its expiry) all return Valid (value 0). Once an EVAL key passes its expiry timestamp, the state reverts to Expired (value 2). No separate enum value is added for EVAL — it is folded into Valid while the key is unexpired, and into Expired once it lapses. There is no LV2_LICENSE_STATE member dedicated to EVAL.

See alsoLicenseState

LV2_FOCUS_REASONEnums Reference

Reason code for a requested focus move.

Confirmed consuming member: MoveFocusRequested event (DISPID 604). Fires when focus move is requested (e.g. Tab). Params: reason (LV2_FOCUS_REASON), Handled.

Values0 = TabForward, 1 = TabBackward, 2 = Programmatic
Registeredsupported Reg-Freeno event sink
VBA
Private Sub m_lv_MoveFocusRequested(ByVal reason As Long, ByRef Handled As Boolean)
    ' reason holds an LV2_FOCUS_REASON value; the event's parameter is typed As Long, not As LV2_FOCUS_REASON, in the handler signature.
End Sub

Gotchas

  • The event's parameter is typed As Long, not As LV2_FOCUS_REASON, in the handler signature — reason merely holds an LV2_FOCUS_REASON value.
  • No Reg-Free consuming member was found within the searched sections: the Events section documents Registered Mode events only, and Reg-Free mode has no VB6/VBA WithEvents event sink.

See alsoMoveFocusRequested

LV2_TRACKING_PREVENTIONEnums Reference

Tracking prevention level.

Confirmed consuming member: GetPreferredTrackingPreventionLevel — Get preferred tracking prevention level for browser profile.

Values0 = None, 1 = Basic, 2 = Balanced, 3 = Strict
Registeredno confirmed consuming member found Reg-Freesupported
VBA
Dim result As LV2_TRACKING_PREVENTION
result = pool.GetPreferredTrackingPreventionLevel(idx)

Gotchas

  • No Registered-mode member referencing this enum was found within the searched sections.

See alsoGetPreferredTrackingPreventionLevel

LV2_MEMORY_USAGEEnums Reference

Memory usage target level.

Values0 = Normal, 1 = Low

Gotchas

  • No consuming member referencing this enum by name was found within the Additional API Reference (6401-9204) or Events (9205-9923) sections.

LV2_SCROLLBAR_STYLEEnums Reference

Scrollbar visual style.

Values0 = Default, 1 = FluentOverlay

Gotchas

  • No consuming member referencing this enum by name was found within the Additional API Reference (6401-9204) or Events (9205-9923) sections — nor anywhere else in the source document. This enum has no confirmed consuming member in this source.

LV2_BOUNDS_MODEEnums Reference

Bounds/coordinate interpretation mode.

Values0 = RawPixels, 1 = RasterizationScale

Gotchas

  • No consuming member referencing this enum by name was found within the Additional API Reference (6401-9204) or Events (9205-9923) sections — nor anywhere else in the source document. This enum has no confirmed consuming member in this source.

LV2_DOWNLOAD_DIALOG_CORNER_ALIGNMENTEnums Reference

Download dialog corner position.

Confirmed consuming member: GetDefaultDownloadDialogCornerAlignment — Get default download dialog corner alignment.

Values0 = TopLeft, 1 = TopRight, 2 = BottomLeft, 3 = BottomRight
Registeredno confirmed consuming member found Reg-Freesupported
VBA
Dim result As LV2_DOWNLOAD_DIALOG_CORNER_ALIGNMENT
result = pool.GetDefaultDownloadDialogCornerAlignment(idx)

Gotchas

  • No Registered-mode member referencing this enum was found within the searched sections.

See alsoGetDefaultDownloadDialogCornerAlignment

LV2_PDF_TOOLBAR_ITEMSEnums Reference

Bitmask of PDF viewer toolbar items to hide (values are combinable, e.g. 1 + 2 hides Save and Print together).

Confirmed consuming members: GetHiddenPdfToolbarItems / SetHiddenPdfToolbarItems.

Values0 = None, 1 = Save, 2 = Print, 4 = SaveAs, 8 = ZoomIn, 16 = ZoomOut
Registeredno confirmed consuming member found Reg-Freesupported
VBA
' Get (Reg-Free)
Dim result As Long
result = pool.GetHiddenPdfToolbarItems(idx)

' Set (Reg-Free)
pool.SetHiddenPdfToolbarItems idx, value

Gotchas

  • Both members type the bitmask as plain Long in their signatures (not as LV2_PDF_TOOLBAR_ITEMS), consistent with its use as a combinable bitmask rather than a single enum member.
  • No Registered-mode member referencing this enum was found within the searched sections.

See alsoGetHiddenPdfToolbarItems, SetHiddenPdfToolbarItems

LiteView2BrowsingDataKindsEnums Reference

Bitmask of browsing-data categories to clear (values are combinable).

Values1 = FileSystems, 2 = IndexedDB, 4 = LocalStorage, 8 = WebSQL, 16 = CacheStorage, 32 = DOMStorage, 64 = Cookies, 128 = AllSite, 256 = DiskCache, 512 = DownloadHistory, 1024 = GeneralAutofill, 2048 = PasswordAutosave, 4096 = BrowsingHistory, 8192 = Settings, 16384 = AllProfile

Gotchas

  • No consuming member referencing this enum by name was found within the Additional API Reference (6401-9204) or Events (9205-9923) sections.

LiteView2ResourceContextEnums Reference

Resource type of a web request.

Confirmed consuming member: WebResourceRequested event (DISPID 18). Fires when a filtered web resource is requested. Set Cancel=True to block.

Values0 = All, 1 = Document, 2 = Stylesheet, 3 = Image, 4 = Media, 5 = Font, 6 = Script, 7 = XHR, 8 = Fetch, 9 = TextTrack, 10 = EventSource, 11 = WebSocket, 12 = Manifest, 13 = Other
Registeredsupported Reg-Freeno event sink
VBA
Private Sub m_lv_WebResourceRequested(ByVal uri As String, ByVal method As String, ByVal resourceContext As Long, ByRef Cancel As Boolean)
    ' resourceContext holds a LiteView2ResourceContext value; the event's parameter is typed As Long, not As LiteView2ResourceContext, in the handler signature.
End Sub

Gotchas

  • The event's parameter is typed As Long, not As LiteView2ResourceContext, in the handler signature — resourceContext merely holds a LiteView2ResourceContext value.
  • No Reg-Free consuming member was found within the searched sections: the Events section documents Registered Mode events only.

See alsoWebResourceRequested

Part III

Troubleshooting and Limits

Critical Safety Warnings

The mistakes below are the ones that cost customers the most time: a synchronous call refused inside an event, a lingering msedgewebview2.exe process that won't let Access exit, a license watermark that won't clear, or a button that silently eats its first click. Each entry states what the warning is, the symptom you'll see if you ignore it, and the exact fix. Nothing here is softened or generalized — if the source documents an exact method name, timer, or property, that exact name is reproduced below.

1. Synchronous calls inside events and host-object calls fail at once (&H80040203)

The warning. Methods that wait for the browser's answer cannot complete while WebView2 is still inside one of its own callbacks. Examples: ExecuteScript, ExecuteScriptWithResult, GetCookies, CallDevToolsProtocolMethod, NavigateSync, CallScriptSync, GetScriptProperty / SetScriptProperty, WaitForElement, and AddScriptToExecuteOnDocumentCreated / EnableLvFacade once the browser exists. LiteView2 refuses them in two places:

Symptom. Error &H80040203 (-2147220989) at once. The description names the event or host object and says what to use instead. Nothing was started; WaitForElement just returns False. (LiteView2 1.0.0.0 instead waited out the timeout, 30 s per call, and some calls crashed the host afterwards.)

Where they work. In ordinary code (buttons, timers) and in the notification events NavigationCompleted, NavigationCompletedHex, SourceChanged, ContentLoading, ContentLoadingHex, DOMContentLoaded, DocumentTitleChanged, HistoryChanged, WebMessageReceived and DevToolsProtocolEventReceived. These are raised after WebView2's callback has returned.

The fix inside an event or host call:

Host objects remain the simplest way for the page to call VBA with typed arguments; inside the host method, use only calls that do not wait.

JSON helpers. JsonGetValue, BuildJson and the other JSON helpers never talk to the browser. They are safe everywhere, including WebMessageReceived.

Reg-Free. A refused pool call raises &H80004005; pool.GetLastErrorCode(idx) gives &H80040203.

Note

See Part I, Chapter 6 for the short version of this warning in context.

2. Reg-Free Mode: skipping DestroyBrowserSync leaves msedgewebview2.exe running

The warning: In Reg-Free Mode, Form_Unload must tear the browser instance down explicitly: pool.ClearReadyCallback idx, then pool.DestroyBrowserSync idx, 2000, then Set pool = Nothing. Registered Mode does not have this problem — the control's own destructor (triggered by Set m_lv = Nothing) handles the equivalent teardown when Access destroys the ActiveX control, and DestroyBrowserSync is a pool-only API that doesn't apply there.

Symptom if ignored: The WebView2 host process keeps running after the form closes and keeps the host application alive with it. Task Manager shows a lingering msedgewebview2.exe — and, in Access, a lingering MSACCESS.EXE — until the OS finally kills them.

The fix — full Reg-Free teardown, in order:

VBA
Private Sub Form_Unload(Cancel As Integer)
    On Error Resume Next
    If Not pool Is Nothing And idx <> 0 Then
        pool.Stop idx                       ' halt any in-flight navigation
        pool.ClearReadyCallback idx         ' detach our callback so it can't fire after teardown
        pool.DestroyBrowserSync idx, 2000   ' synchronous browser teardown (max 2 s wait)
        idx = 0
    End If
    Set pool = Nothing                      ' release the pool reference
End Sub

The same in-flight-navigation risk (item 1 below) applies to both modes: a navigation still running when the form closes can fire NavigationCompleted against a half-destroyed control, and an async ready callback that hasn't fired yet can trigger after VBA references are gone. Stop and ClearReadyCallback / Set m_lv = Nothing are what guard against those two, respectively, in each mode.

Note

See Part I, Chapter 17 for the short version of this warning in context.

3. ActivateLicense must run before the first Navigate — never inside WebViewReady / OnBrowserReady

The warning: Two hard rules on timing:

Symptom if ignored:

The fix: Call ActivateLicense from Form_Load / UserForm_Initialize, on every launch — activation is session-only and does not persist across restarts. Keep the key in one shared module rather than pasting it into per-form code: modLV2License.bas (Registered) exports EnsureLicensed(ctrl), which each form calls once in Form_Load; modLV2Pool.bas (Reg-Free) activates the license automatically, inside GetPool(), on the first call in the process. Both helpers are idempotent — EnsureLicensed checks a flag and exits early on later calls, GetPool only initializes once — so calling them more than once causes no harm. Rotating the key means editing one file, not every form.

ActivateLicense is process-wide, not per-form and not per-browser: one successful call activates every LiteView2 browser created afterward in the same Access/Office session, and the Reg-Free pool shares the activated license across every CreateInControl call automatically — you do not register the license per browser-index.

Registered Mode:

VBA
m_lv.ActivateLicense "My Company", "V1|...|..."
Debug.Print "Status: " & m_lv.LicenseStatus
Debug.Print "Type: " & m_lv.LicenseType
Debug.Print "State: " & m_lv.LicenseState
Debug.Print "Days remaining: " & m_lv.TrialDaysRemaining
Debug.Print "Expiry: " & m_lv.LicenseExpiry
Debug.Print "Version: " & m_lv.LicenseVersion
Debug.Print "Info JSON: " & m_lv.GetLicenseInfo()

Reg-Free:

VBA
pool.ActivateLicense "My Company", "V1|...|..."
Debug.Print "Status: " & pool.LicenseStatus
Debug.Print "Type: " & pool.LicenseType
Debug.Print "State: " & pool.LicenseState
Debug.Print "Trial days: " & pool.TrialDaysRemaining
Debug.Print "Info JSON: " & pool.GetLicenseInfo()

The key argument is an opaque V1 activation string. The runtime validates it and enforces any expiry timestamp it carries. Activation is in-memory only for the current process — no registry, no file system, no network call. If no key is supplied in code, the 30-day Trial Period applies.

Note

elsewhere in this cookbook, the Reg-Free LicenseStatus / LicenseType / LicenseState / TrialDaysRemaining properties are also documented as index-scoped Get-methods — pool.GetLicenseStatus browserIndex, value and similarly for the others — in the auto-synced IDL reference, which conflicts with the index-free pool.LicenseStatus form shown above. The index-free form is used here because it matches the process-wide activation semantics documented in this section (one activation call covers every browser in the pool). See Part II → Licensing for the full picture on both forms.

Note

See Part I, Chapter 21 for the short version of this warning in context.

4. Access swallows the first click when focus is inside the browser — mirror Click with MouseDown

The warning: Any external button whose action needs to fire on the very first physical mouse click needs a MouseDown handler alongside its Click handler, whenever focus may currently be inside the LiteView2 browser surface.

Symptom if ignored: The button's Click event does not fire on the first click. Access uses that first click on an external control to move focus off the browser and onto the control; the click that does that is spent moving focus rather than triggering Click. The action only fires starting from the second click, which looks like an intermittent, hard-to-reproduce dead button to anyone testing it once.

The fix: Keep Click for keyboard-driven activation (Enter/Space while the button has focus), and add a MouseDown handler with the same action so the first physical mouse click also fires it, regardless of where focus was a moment before.

Note

See Part I, Chapter 2 for the short version of this warning in context.

5. Ordering matters: SetLocalContentRoot before Navigate; AddHostObjectToScript before the Navigate that uses it

The warning: SetLocalContentRoot, host-object registration, and the first Navigate all belong in the ready event — LiteView2Ctrl1_WebViewReady (Registered) or OnBrowserReady (Reg-Free) — not in Form_Load. Within the ready handler, the order is fixed: SetLocalContentRoot → AreHostObjectsAllowed → AddHostObjectToScript → Navigate. Host objects specifically must be added before the navigation that uses them. Two calls belong in Form_Load, after EnsureLicensed: EnableLvFacade and AddScriptToExecuteOnDocumentCreated. Before the browser exists they are queued and applied before the first page. Inside WebViewReady they fail at once with &H80040203.

Symptom if ignored:

The fix:

VBA
' ❌ WRONG — Form_Load runs BEFORE WebView2 is ready.
' These calls silently no-op, race with init, or cause a stuck watermark.
Private Sub Form_Load()
    Set m_lv = Me.LiteView2Ctrl1.Object
    m_lv.SetLocalContentRoot CurrentProject.Path        ' ❌ wait for WebViewReady
    m_lv.AddHostObjectToScript "vba", Me                ' ❌ wait for WebViewReady
    m_lv.Navigate "https://lv2.example/index.html"      ' ❌ wait for WebViewReady
End Sub
VBA
' ✅ CORRECT — Form_Load only acquires the typed reference + activates the license.
' Activation key lives in modLV2License.bas, not duplicated here.
Private Sub Form_Load()
    Set m_lv = Me.LiteView2Ctrl1.Object
    EnsureLicensed m_lv                      ' from modLV2License — once per process
End Sub

Private Sub LiteView2Ctrl1_WebViewReady()
    m_lv.SetLocalContentRoot CurrentProject.Path
    m_lv.AreHostObjectsAllowed = True
    m_lv.AddHostObjectToScript "vba", Me
    m_lv.Navigate "https://lv2.example/index.html"
End Sub

The same anti-pattern applies to Reg-Free Mode: Set pool = GetPool() (which activates the license internally), CreateInControl, and SetReadyCallback belong in Form_Load; SetLocalContentRoot / SetAreHostObjectsAllowed / AddHostObjectToScript / Navigate all move into OnBrowserReady.

Following these three rules — activation key in a shared module, SetLocalContentRoot before Navigate, AddHostObjectToScript before Navigate — is, per this cookbook, what makes most startup problems disappear.

Note

See Part I, Chapter 5 for the short version of this warning in context.

Troubleshooting by Symptom

Before chasing a specific symptom below, confirm the three basics that account for most reported problems: SetLocalContentRoot and AddHostObjectToScript are called before Navigate, all three live inside the ready handler (not Form_Load), and the activation key lives in one shared module (modLV2License for Registered, modLV2Pool for Reg-Free) rather than being pasted into a form. If those hold, use the table below to jump to the symptom you're seeing, then read the matching detail section for the code fix.

Ready-handler order (read this first)

Almost every startup symptom in this section — the browser never appearing ready, Navigate doing nothing, host objects being undefined in JavaScript — comes back to one rule: WebViewReady (Registered) and OnBrowserReady (Reg-Free) fire asynchronously, after Form_Load has already returned. Form_Load should only acquire the control reference and activate the license. Everything that talks to the page — SetLocalContentRoot, AreHostObjectsAllowed, AddHostObjectToScript, Navigate — belongs inside the ready handler, in that order. Two calls belong in Form_Load, after EnsureLicensed: EnableLvFacade and AddScriptToExecuteOnDocumentCreated. Before the browser exists they are queued and applied before the first page. Inside WebViewReady they fail at once with &H80040203.

VBA
' ❌ WRONG — Form_Load runs BEFORE WebView2 is ready.
' These calls silently no-op, race with init, or cause a stuck watermark.
Private Sub Form_Load()
    Set m_lv = Me.LiteView2Ctrl1.Object
    m_lv.SetLocalContentRoot CurrentProject.Path        ' ❌ wait for WebViewReady
    m_lv.AddHostObjectToScript "vba", Me                ' ❌ wait for WebViewReady
    m_lv.Navigate "https://lv2.example/index.html"      ' ❌ wait for WebViewReady
End Sub
VBA
' ✅ CORRECT — Form_Load only acquires the typed reference + activates the license.
Private Sub Form_Load()
    Set m_lv = Me.LiteView2Ctrl1.Object
    EnsureLicensed m_lv                      ' from modLV2License — once per process
End Sub

Private Sub LiteView2Ctrl1_WebViewReady()
    m_lv.SetLocalContentRoot CurrentProject.Path
    m_lv.AreHostObjectsAllowed = True
    m_lv.AddHostObjectToScript "vba", Me
    m_lv.Navigate "https://lv2.example/index.html"
End Sub

Reg-Free mode follows the same split: Set pool = GetPool() (which activates the license), CreateInControl, and SetReadyCallback go in Form_Load; SetLocalContentRoot, SetAreHostObjectsAllowed, AddHostObjectToScript, and Navigate move into OnBrowserReady. None of these calls raise an error when placed too early — they silently no-op or fail — which is why the symptom always looks like "nothing happened" rather than a clear exception.

Quick reference

SymptomMost likely causeFix
Browser never becomes ready (WebViewReady / OnBrowserReady never fires)Setup code was placed in Form_Load instead of the ready handler, so it silently no-oped — this is usually mistaken for the event itself not firing. In Reg-Free mode, SetReadyCallback may not have actually been registered.Move SetLocalContentRoot / AddHostObjectToScript / Navigate into the ready handler (see above). Confirm SetReadyCallback runs in Form_Load alongside CreateInControl.
Navigate does nothingNavigate executed before SetLocalContentRoot, or called from Form_Load before the control is ready.Call SetLocalContentRoot BEFORE the first Navigate, both inside WebViewReady / OnBrowserReady.
Local files don't load — "Can't reach this page" or 404SetLocalContentRoot not called, called with the wrong folder, or the URL points outside the mapped folder.Map CurrentProject.Path; verify the target file exists in that folder; use forward slashes in the URL. See "Wrong local content root" below.
Local content loads from the wrong folder, or an old file keeps appearingThe disk folder passed to SetLocalContentRoot doesn't directly contain the HTML you're navigating to (wrong root level or subfolder confusion).Pick the folder that directly contains the target HTML; don't over-shoot to a parent, and don't double up a subfolder in both the mapped root and the URL. See table below.
window.chrome.webview.hostObjects.sync.vba is undefined in JSAddHostObjectToScript was called AFTER Navigate. Host objects only bind on the NEXT navigation.Order inside the ready handler: SetLocalContentRoot → AreHostObjectsAllowed → AddHostObjectToScript → Navigate.
JavaScript cannot call VBA (host object exists, method call fails or does nothing)AreHostObjectsAllowed wasn't set True, or the method the page is calling isn't a Public Sub in the form's code module.Set AreHostObjectsAllowed = True before AddHostObjectToScript; make every method the page calls via hostObjects.sync.vba.<name>() a Public Sub.
A call fails at once with error &H80040203 (-2147220989)It was made inside an inline event (WebViewReady, NavigationStarting, …) or inside a VBA method the page called through a host object; the call waits for the browser, which cannot answer there. Nothing was started.Use ExecuteScriptAsync / PostWebMessageAsJson / Navigate there, or move the call to NavigationCompleted, WebMessageReceived, a button or a timer. Reg-Free: the pool reports &H80004005; GetLastErrorCode(idx) = &H80040203.
A call times out with &H800705B4The page did not answer within SynchronousTimeOut (ExecuteScript) or the fixed limit of that call.Check the page's JavaScript; raise SynchronousTimeOut for long scripts. ExecuteScriptWithResult reports this as succeeded = False instead of an error.
First click on a form button does nothing; second click worksAccess uses the first click on an external button to move focus to that button; Click doesn't fire on that click.Mirror Click into a MouseDown handler for any button reachable while focus is inside the browser. Keep Click for keyboard activation.
Set m_lv = Me.LiteView2Ctrl1 raises "Type mismatch"Missing .Object — Access's form-control wrapper isn't QueryInterface-compatible with the typed coclass.Set m_lv = Me.LiteView2Ctrl1.Object.
IntelliSense doesn't show LiteView2 methods after m_lv."LiteView2 1.0 Type Library" not checked in Tools → References, OR m_lv declared As Object (late-bound).Check the type library reference; declare Private m_lv As LiteView2Lib.LiteView2Ctrl.
Reg-Free ready/message callback does not fireIt's asynchronous and hasn't fired yet, ClearReadyCallback detached it early, or a stray callback is silently no-oping against the idx = 0 teardown sentinel.Confirm SetReadyCallback ran in Form_Load; confirm nothing calls ClearReadyCallback before the browser had a chance to become ready.
Access/Excel doesn't exit; msedgewebview2.exe / MSACCESS.EXE linger in Task ManagerReg-Free mode is missing DestroyBrowserSync in Form_Unload. The WebView2 host process keeps the Office process alive.Add pool.ClearReadyCallback idx, pool.DestroyBrowserSync idx, 2000, then Set pool = Nothing to Form_Unload.
Watermark renders despite a valid keyActivation didn't happen before the first navigation — EnsureLicensed not called from Form_Load, LV2_KEY empty, or ActivateLicense called too late (after Navigate, or from inside the ready handler).Confirm the shared license module runs EnsureLicensed / activates inside GetPool() before any navigation. Activation must happen before the first Navigate, never inside WebViewReady / OnBrowserReady.
Stale cookies / session data — old content or a stale login persists across runsSetLocalContentRoot always maps to the same fixed virtual host (https://lv2.example/) regardless of which disk folder is mapped, so cookies/storage set under that origin persist across app restarts and across different mapped folders.Call ClearCookies for cookies and/or ClearBrowsingData (e.g. LV2_DATA_ALL_PROFILE) for cache and other storage — see the "Stale cookies / session data" detail below and Part II → Cookies and Browsing Data.
Downloads don't happen, or a download dialog seems stuckAllowDownloads is False, or HiddenDownloadUI is hiding an in-progress download dialog the user expects to see.Check AllowDownloads is True if downloads should be allowed; if HiddenDownloadUI is on, check the target folder before assuming a hidden download failed.
PrintToPdf doesn't produce a file, or you're not sure it's supportedRuntime doesn't support it (unchecked HasPrintToPdf), or — Reg-Free only — the call is fire-and-forget and the file simply hasn't finished writing yet.Gate the call behind HasPrintToPdf. In Reg-Free mode, don't treat an immediately-missing PDF as a failure — the call doesn't report completion.
Reg-Free browsers won't create / suspected runtime problemThe WebView2 Runtime is missing or an unexpected version on the machine.Check IsWebView2RuntimeInstalled, GetWebView2RuntimeVersion, GetWebView2RuntimePath (Reg-Free / pool only).
Browsers/profiles not cleaning up; repeated stale msedgewebview2.exe processesDestroyBrowserSync wasn't called for every browser index, or wasn't given enough time to finish.Call pool.DestroyBrowserSync idx, 2000 for every index in teardown; audit/force-clear stragglers with the pool's parked-browser APIs (see below).

Detail and code

Local HTML returns 404 / "can't reach this page"

This is almost always a mapping problem, not a missing-file problem in the way it first appears. SetLocalContentRoot folder maps a folder on disk to the fixed virtual host https://lv2.example/, one-to-one — the folder you pass becomes the URL root. See "Wrong local content root" immediately below for the mapping table and the specific mistakes that produce this symptom. If the mapping is correct, the last thing to check is that the target file physically exists in the mapped folder — WebView2 shows its own "page can't be reached" error in that case, which looks like a LiteView2 problem but isn't.

Wrong local content root / path-mapping mistakes

Disk path you passURL rootExample file on diskURL to navigate to
C:\Apps\MyDB\https://lv2.example/C:\Apps\MyDB\index.htmlhttps://lv2.example/index.html
C:\Apps\MyDB\https://lv2.example/C:\Apps\MyDB\pages\admin.htmlhttps://lv2.example/pages/admin.html
CurrentProject.Path (e.g. C:\Apps\MyDB)https://lv2.example/the form's folderhttps://lv2.example/<any-file-in-that-folder>

Common mistakes:

See Part II → Local Content & Navigation for the full reference.

window.chrome.webview.hostObjects.sync.vba is undefined

Check it defensively from the page before calling into it, and remember the object only exists after a navigation that happened after AddHostObjectToScript ran:

JavaScript
if (window.chrome && window.chrome.webview &&
    window.chrome.webview.hostObjects.sync.vba) {
    // safe to call window.chrome.webview.hostObjects.sync.vba.<Method>(...)
} else {
    console.error("vba host object not bound yet");
}

If this check fails on a page you expect to have the host object, the almost-certain cause is AddHostObjectToScript running after Navigate for that page load — see the ready-handler order above.

JavaScript cannot call VBA

Beyond the ordering rule above, two more documented requirements have to hold:

  1. AreHostObjectsAllowed = True must be set before AddHostObjectToScript — it's the gate in the documented ready-handler order (SetLocalContentRoot → AreHostObjectsAllowed → AddHostObjectToScript → Navigate).
  2. Every method the page calls via hostObjects.sync.vba.<name>() must exist as a Public Sub in the form's code module — this is called out explicitly as a checklist item.
VBA
Private Sub LiteView2Ctrl1_WebViewReady()
    m_lv.SetLocalContentRoot CurrentProject.Path
    m_lv.AreHostObjectsAllowed = True
    m_lv.AddHostObjectToScript "vba", Me
    m_lv.Navigate "https://lv2.example/index.html"
End Sub

Public Sub SaveCustomer(ByVal custName As String)
    ' Must be Public — the page calls this by name.
    MsgBox "Saving " & custName
End Sub
HTML
<input id="txtName-4" type="text">
<button onclick="save()">Save</button>
<script>
function save() {
    window.chrome.webview.hostObjects.sync.vba.SaveCustomer(
        document.getElementById('txtName').value);
}
</script>

VBA cannot execute JavaScript

If the call appears to do nothing, recheck the ready-handler order above — a page that hasn't finished navigating yet has nothing to execute against.

If a call raises &H80040203, it was made inside an inline event or a host-object call; see Critical Safety Warnings #1. WebMessageReceived is not such a place: you can parse and act on the message inline:

VBA
' Fine: WebMessageReceived runs after WebView2's callback has returned.
Private Sub LiteView2Ctrl1_WebMessageReceived(ByVal message As String, ByVal source As String)
    Dim orderId As Variant
    orderId = m_lv.JsonGetValue(message, "orderId")
    ' ... act on orderId; ExecuteScript and the other synchronous calls work here too ...
End Sub

Caution

a host object is the simplest way for the page to call a VBA method directly. Inside that method, use only calls that do not wait for the browser (ExecuteScriptAsync, PostWebMessageAsJson, the JSON helpers, DAO). A synchronous ExecuteScript there fails with &H80040203.

First click on an Access form button appears ignored

Access uses the first click on any form button to move focus to that button when focus is currently inside an embedded ActiveX control (LiteView2, the legacy WebBrowser control, Microsoft DatePicker — all the same). On that first click, the button's Click event does not fire; the user has to click again. This is long-standing Access behavior, not a LiteView2 bug.

VBA
Private Sub cmdSave_Click()
    DoSave  ' the actual work
End Sub

Private Sub cmdSave_MouseDown(Button As Integer, Shift As Integer, _
                              X As Single, Y As Single)
    If Button = 1 Then DoSave  ' left mouse button only
End Sub

Private Sub DoSave()
    If m_lv Is Nothing Then Exit Sub
    m_lv.ExecuteScriptAsync "saveContent()"
End Sub

MouseDown fires the instant the mouse button goes down, regardless of focus state, so the action runs on the first physical click. Keep the Click handler so keyboard activation (Enter / Spacebar) still works. Apply this to any button clicked while focus may be inside the LiteView2 control; buttons triggered only from VBA code (e.g. cmdSave.Value = True) don't need it.

"Type mismatch" when acquiring the control reference

Set m_lv = Me.LiteView2Ctrl1 raises "Type mismatch" because Access's form-control wrapper isn't QueryInterface-compatible with the typed coclass. The fix is one word:

VBA
Set m_lv = Me.LiteView2Ctrl1.Object

.Object peels Access's wrapper to expose the underlying ActiveX control.

IntelliSense is missing for LiteView2 methods

Two independent causes, check both:

VBA
Private m_lv As LiteView2Lib.LiteView2Ctrl   ' not: Private m_lv As Object

Reg-Free ready/message callback does not fire

SetReadyCallback is registered in Form_Load, alongside CreateInControl; OnBrowserReady then fires later, asynchronously, once the browser is actually ready — checking for its effects immediately after Form_Load returns will look exactly like it never fired.

Two other documented mechanisms can also make it look silent:

See "Access/Excel does not exit" below for the full Reg-Free teardown sequence these two calls belong to.

Access/Excel does not exit after a Reg-Free browser closes

Reg-Free Mode requires explicit teardown. Without it, the WebView2 host process (msedgewebview2.exe) keeps the Office process alive after the form closes — Task Manager shows lingering msedgewebview2.exe and MSACCESS.EXE / EXCEL.EXE until the OS eventually kills them.

VBA
Private Sub Form_Unload(Cancel As Integer)
    On Error Resume Next
    If Not pool Is Nothing And idx <> 0 Then
        pool.Stop idx                       ' halt any in-flight navigation
        pool.ClearReadyCallback idx         ' detach our callback so it can't fire after teardown
        pool.DestroyBrowserSync idx, 2000   ' synchronous browser teardown (max 2 s wait)
        idx = 0
    End If
    Set pool = Nothing                      ' release the pool reference
End Sub

pool.DestroyBrowserSync idx, 2000 is the critical call — it tears down the browser instance synchronously, waiting up to 2 seconds for in-process cleanup. Skipping it is the single most common cause of this symptom. On Error Resume Next is deliberate here too: by the time Form_Unload runs, the form may already be closing because of an earlier error, and a second error popping a MsgBox during shutdown produces a form the user can't dismiss cleanly.

Registered Mode does not need DestroyBrowserSync — it's a pool-only API. Set m_lv = Nothing in Form_Close (after m_lv.Stop) is sufficient; the control's own destructor handles equivalent cleanup when Access tears the form down.

Watermark/license issue despite a valid key

Activation is process-wide, not per-form and not per-browser: one successful ActivateLicense call (via EnsureLicensed or inside GetPool()) activates every LiteView2 browser created afterwards in the same Access/Office session, and the Reg-Free pool shares it across every CreateInControl call automatically. It does not persist across process restarts — each fresh Access/Office session must activate once.

Given that, a watermark despite a key you know is valid comes down to one of:

The activation key must live in exactly one shared module (modLV2License.bas for Registered, modLV2Pool.bas for Reg-Free) — never duplicated into per-form code. The shared-module call is idempotent (EnsureLicensed checks a flag and exits early on repeat calls; GetPool only initializes once), so calling it more than once by accident is harmless — the danger is calling it too late or not at all, not calling it twice.

To confirm activation actually took effect in Reg-Free mode, you can read back the status:

VBA
Debug.Print "License status: " & pool.LicenseStatus

Note

The source documents license-status reads two different ways in Reg-Free mode: an index-free pool.LicenseStatus property (used above, consistent with activation being process-wide rather than per-browser) in one section, and a pool.GetLicenseStatus browserIndex, value Get-method call in another. This chapter uses the index-free form as primary since it matches the documented process-wide semantics; see Part II → Licensing for the full picture.

Stale cookies / session data

SetLocalContentRoot always maps to the same fixed virtual host, https://lv2.example/, regardless of which disk folder you point it at (see the path-mapping table above). Because the browser sees the same origin every time, cookies, cache, and page-owned localStorage/sessionStorage set on an earlier run — or under a previous SetLocalContentRoot target — persist under that origin across app restarts. A page can look like it's "ignoring" new content in the mapped folder when what's actually happening is stale storage from an earlier session under that same origin.

LiteView2 documents dedicated APIs for exactly this — reach for these first:

VBA
' Registered — clear cookies and everything else for a full reset
m_lv.ClearCookies
m_lv.ClearBrowsingData 16384   ' LV2_DATA_ALL_PROFILE

Cookies, cache/browsing data, and page-owned localStorage/sessionStorage are three distinct things (Chapter 12 covers the distinction in full) — but ClearBrowsingData's bitmask reaches all of them, so a full reset does not require leaving VBA. If you specifically need to clear storage from inside the page itself (for example, a page-side "reset" button), ExecuteScriptAsync "localStorage.clear(); sessionStorage.clear();" remains an option — but it does not touch cookies or the HTTP cache, so it is not a substitute for ClearCookies/ClearBrowsingData when the actual symptom is a stuck login or stale cookies.

Download problems

Two properties documented for downloads explain most reports:

Check AllowDownloads first if downloads should be allowed at all; if HiddenDownloadUI is intentionally on, check the target folder for the completed file before treating a "stuck" download as a bug. See Part II → Downloads & Printing for exact signatures and defaults.

Print/PDF problems

Gate PrintToPdf behind the capability check — not every WebView2 runtime supports it:

VBA
' Registered
If m_lv.HasPrintToPdf Then
    m_lv.PrintToPdf "C:\output.pdf"
End If
VBA
' Reg-Free
If pool.HasPrintToPdf(idx) Then
    pool.PrintToPdf idx, "C:\output.pdf"
End If

Caution

In Reg-Free mode, PrintToPdf is fire-and-forget — the call returns immediately and doesn't report success, failure, or when the file has finished writing. A PDF that isn't sitting in the target folder the instant the call returns isn't necessarily a bug; check again a moment later before treating it as a failure.

The same capability-check pattern applies to HasCapturePreview for screenshot support:

VBA
' Registered
Debug.Print "Screenshot support: " & m_lv.HasCapturePreview
VBA
' Reg-Free
Debug.Print "Screenshot support: " & pool.HasCapturePreview(idx)

WebView2 runtime/environment issue

Reg-Free mode exposes runtime detection directly on the pool (Pool-Only — no Registered equivalent in this material):

VBA
If pool.IsWebView2RuntimeInstalled Then
    Debug.Print "Version: " & pool.GetWebView2RuntimeVersion
    Debug.Print "Path: " & pool.GetWebView2RuntimePath
End If

If IsWebView2RuntimeInstalled returns False, the machine is missing the WebView2 Runtime that LiteView2 depends on for both modes — Reg-Free browsers won't create, and this is the first thing to check before assuming a code-level bug.

Browser/profile cleanup issues

The one call that matters for cleanup is documented in full under "Access/Excel does not exit" above: pool.DestroyBrowserSync idx, 2000 must run for every browser index your form created, in teardown, before releasing the pool reference. Skipping it — or not giving it enough time — is why lingering msedgewebview2.exe processes show up in Task Manager.

For auditing and forcing cleanup of browsers that were parked rather than fully destroyed, the pool API also documents GetParkedBrowserCount and DestroyAllParked. This material doesn't cover their exact signatures — see Part II → Reg-Free Pool Management for the full reference — but the pattern to reach for is: use GetParkedBrowserCount to confirm whether stragglers actually exist before assuming a leak, and DestroyAllParked to force-clear them rather than debugging each index by hand.