
Following (at least trying

When I finish loading a web, I add a JS function with the function MutationObserver() with the procedure MutationObserverSet(webView)
Then I activate an eventHandler to capture the console output messages from the WebViewGadget using the procedure
WebViewSetWebMessageReceivedEventHandler()
Code: Select all
;--------------------------------------
; https://learn.microsoft.com/en-us/microsoft-edge/webview2/concepts/navigation-events
CompilerIf Defined(IID_IUnknown, #PB_Label) = #False
DataSection
IID_IUnknown:
Data.l $00000000
Data.w $0000, $0000
Data.b $C0, $00, $00, $00, $00, $00, $00, $46
EndDataSection
CompilerEndIf
;- STRUCTURES
Structure IUnknownBase_Structure
*pVtbl
*pQueryInterface
*pAddRef
*pRelease
*pInvoke
lRefCount.l
Token.q
hEvent.i
EndStructure
Structure ICoreWebView2ExecuteScriptCompletedHandler_Structure Extends IUnknownBase_Structure
Result$
EndStructure
Structure ICoreWebView2NavigationCompletedEventHandler_Structure Extends IUnknownBase_Structure
*pFunction
EndStructure
Structure ICoreWebView2ContentLoadingEventHandler_Structure Extends IUnknownBase_Structure
*pFunction
EndStructure
Structure ICoreWebView2WebMessageReceivedEventHandler_Structure Extends IUnknownBase_Structure
*pFunction
EndStructure
;--------------------------------------
;- NavigationCompleted
Global NewMap MapNavigationCompletedEventHandler.ICoreWebView2NavigationCompletedEventHandler_Structure()
Procedure.l ICoreWebView2NavigationCompletedEventHandler_QueryInterface(*this.IUnknownBase_Structure, *riid.IID, *ppvObject.Integer)
If *ppvObject And *riid
If CompareMemory(*riid, ?IID_IUnknown, SizeOf(IID))
*this\lRefCount + 1
*ppvObject\i = *this
Else
*ppvObject\i = 0
ProcedureReturn #E_NOINTERFACE
EndIf
Else
ProcedureReturn #E_POINTER
EndIf
ProcedureReturn #S_OK
EndProcedure
Procedure.l ICoreWebView2NavigationCompletedEventHandler_AddRef(*this.IUnknownBase_Structure)
*this\lRefCount + 1
ProcedureReturn *this\lRefCount
EndProcedure
Procedure.l ICoreWebView2NavigationCompletedEventHandler_Release(*this.IUnknownBase_Structure)
*this\lRefCount - 1
ProcedureReturn *this\lRefCount
EndProcedure
Procedure.l ICoreWebView2NavigationCompletedEventHandler_Invoke(*this.ICoreWebView2NavigationCompletedEventHandler_Structure, *sender.ICoreWebView2, *args.ICoreWebView2NavigationCompletedEventArgs)
Protected isSuccess, *uri, uri.s
If *args And *args\get_IsSuccess(@isSuccess) = #S_OK And isSuccess
If *sender
If *sender\get_Source(@*uri) = #S_OK
If *uri
uri = PeekS(*uri)
If *this\pFunction
CallFunctionFast(*this\pFunction, @uri)
EndIf
CoTaskMemFree_(*uri)
EndIf
;-zikichange
;*sender\add_WebMessageReceived = *sender\
EndIf
EndIf
EndIf
ProcedureReturn #S_OK
EndProcedure
Procedure.i WebViewSetNavigateCompleteEventHandler(WebView, *EventHandler)
Protected Result.i
Protected Controller.ICoreWebView2Controller, Core.ICoreWebView2
Protected *NavigationCompletedEventHandler.ICoreWebView2NavigationCompletedEventHandler_Structure
Protected Token.q
If GadgetType(WebView) = #PB_GadgetType_WebView And *EventHandler <> #Null
Controller = GetGadgetAttribute(WebView, #PB_WebView_ICoreController)
If Controller
If Controller\get_CoreWebView2(@Core) = #S_OK And Core <> #Null
If FindMapElement(MapNavigationCompletedEventHandler(), Str(WebView))
If MapNavigationCompletedEventHandler()\Token
Core\remove_NavigationCompleted(MapNavigationCompletedEventHandler()\Token)
EndIf
DeleteMapElement(MapNavigationCompletedEventHandler())
EndIf
*NavigationCompletedEventHandler = AddMapElement(MapNavigationCompletedEventHandler(), Str(WebView))
If *NavigationCompletedEventHandler
*NavigationCompletedEventHandler\pVtbl = *NavigationCompletedEventHandler + OffsetOf(IUnknownBase_Structure\pQueryInterface)
*NavigationCompletedEventHandler\pQueryInterface = @ICoreWebView2NavigationCompletedEventHandler_QueryInterface()
*NavigationCompletedEventHandler\pAddRef = @ICoreWebView2NavigationCompletedEventHandler_AddRef()
*NavigationCompletedEventHandler\pRelease = @ICoreWebView2NavigationCompletedEventHandler_Release()
*NavigationCompletedEventHandler\pInvoke = @ICoreWebView2NavigationCompletedEventHandler_Invoke()
*NavigationCompletedEventHandler\pFunction = *EventHandler
If Core\add_NavigationCompleted(*NavigationCompletedEventHandler, @*NavigationCompletedEventHandler\Token) = #S_OK
Result = #True
Else
DeleteMapElement(MapNavigationCompletedEventHandler())
EndIf
EndIf
EndIf
Core\Release()
EndIf
EndIf
ProcedureReturn Result
EndProcedure
;- ContentLoading
Global NewMap MapContentLoadingEventHandler.ICoreWebView2ContentLoadingEventHandler_Structure()
Procedure.l ICoreWebView2ContentLoadingEventHandler_QueryInterface(*this.IUnknownBase_Structure, *riid.IID, *ppvObject.Integer)
If *ppvObject And *riid
If CompareMemory(*riid, ?IID_IUnknown, SizeOf(IID))
*this\lRefCount + 1
*ppvObject\i = *this
Else
*ppvObject\i = 0
ProcedureReturn #E_NOINTERFACE
EndIf
Else
ProcedureReturn #E_POINTER
EndIf
ProcedureReturn #S_OK
EndProcedure
Procedure.l ICoreWebView2ContentLoadingEventHandler_AddRef(*this.IUnknownBase_Structure)
*this\lRefCount + 1
ProcedureReturn *this\lRefCount
EndProcedure
Procedure.l ICoreWebView2ContentLoadingEventHandler_Release(*this.IUnknownBase_Structure)
*this\lRefCount - 1
ProcedureReturn *this\lRefCount
EndProcedure
Procedure.l ICoreWebView2ContentLoadingEventHandler_Invoke(*this.ICoreWebView2ContentLoadingEventHandler_Structure, *sender.ICoreWebView2, *args.ICoreWebView2ContentLoadingEventArgs)
Protected isSuccess, *uri, uri.s
;If *args And *args\get_IsSuccess(@isSuccess) = #S_OK And isSuccess
If *sender
If *sender\get_Source(@*uri) = #S_OK
If *uri
uri = PeekS(*uri)
If *this\pFunction
CallFunctionFast(*this\pFunction, @uri)
EndIf
CoTaskMemFree_(*uri)
EndIf
EndIf
EndIf
;EndIf
ProcedureReturn #S_OK
EndProcedure
Procedure.i WebViewSetContentLoadingEventHandler(WebView, *EventHandler)
Protected Result.i
Protected Controller.ICoreWebView2Controller, Core.ICoreWebView2
Protected *ContentLoadingEventHandler.ICoreWebView2ContentLoadingEventHandler_Structure
Protected Token.q
If GadgetType(WebView) = #PB_GadgetType_WebView And *EventHandler <> #Null
Controller = GetGadgetAttribute(WebView, #PB_WebView_ICoreController)
If Controller
If Controller\get_CoreWebView2(@Core) = #S_OK
If Core
If FindMapElement(MapContentLoadingEventHandler(), Str(WebView))
If MapContentLoadingEventHandler()\Token
Core\remove_ContentLoading(MapContentLoadingEventHandler()\Token)
EndIf
DeleteMapElement(MapContentLoadingEventHandler())
EndIf
*ContentLoadingEventHandler = AddMapElement(MapContentLoadingEventHandler(), Str(WebView))
If *ContentLoadingEventHandler
*ContentLoadingEventHandler\pVtbl = *ContentLoadingEventHandler + OffsetOf(IUnknownBase_Structure\pQueryInterface)
*ContentLoadingEventHandler\pQueryInterface = @ICoreWebView2ContentLoadingEventHandler_QueryInterface()
*ContentLoadingEventHandler\pAddRef = @ICoreWebView2ContentLoadingEventHandler_AddRef()
*ContentLoadingEventHandler\pRelease = @ICoreWebView2ContentLoadingEventHandler_Release()
*ContentLoadingEventHandler\pInvoke = @ICoreWebView2ContentLoadingEventHandler_Invoke()
*ContentLoadingEventHandler\pFunction = *EventHandler
If Core\add_ContentLoading(*ContentLoadingEventHandler, @*ContentLoadingEventHandler\Token) = #S_OK
;Debug *ContentLoadingEventHandler\Token
Result = #True
Else
DeleteMapElement(MapContentLoadingEventHandler())
EndIf
EndIf
Core\Release()
EndIf
EndIf
EndIf
EndIf
ProcedureReturn Result
EndProcedure
;- WebMessageReceived
Global NewMap MapMessageReceivedEventHandler.ICoreWebView2WebMessageReceivedEventHandler_Structure()
Procedure.l ICoreWebView2WebMessageReceivedEventHandler_QueryInterface(*this.IUnknownBase_Structure, *riid.IID, *ppvObject.Integer)
If *ppvObject And *riid
If CompareMemory(*riid, ?IID_IUnknown, SizeOf(IID))
*this\lRefCount + 1
*ppvObject\i = *this
Else
*ppvObject\i = 0
ProcedureReturn #E_NOINTERFACE
EndIf
Else
ProcedureReturn #E_POINTER
EndIf
ProcedureReturn #S_OK
EndProcedure
Procedure.l ICoreWebView2WebMessageReceivedEventHandler_AddRef(*this.IUnknownBase_Structure)
*this\lRefCount + 1
ProcedureReturn *this\lRefCount
EndProcedure
Procedure.l ICoreWebView2WebMessageReceivedEventHandler_Release(*this.IUnknownBase_Structure)
*this\lRefCount - 1
ProcedureReturn *this\lRefCount
EndProcedure
Procedure.l ICoreWebView2WebMessageReceivedEventHandler_Invoke(*this.ICoreWebView2WebMessageReceivedEventHandler_Structure, *sender.ICoreWebView2, *args.ICoreWebView2WebMessageReceivedEventArgs)
Protected message, *uri, uri.s
Debug uri
If *args And *args\TryGetWebMessageAsString(@message) = #S_OK And message
If PeekS(message) = "PBWEB content changed!"
Debug PeekS(message)
If *sender
If *sender\get_Source(@*uri) = #S_OK
If *uri
uri = PeekS(*uri)
If *this\pFunction
CallFunctionFast(*this\pFunction, @uri)
EndIf
CoTaskMemFree_(*uri)
EndIf
EndIf
EndIf
EndIf
EndIf
EndProcedure
Procedure.i WebViewSetWebMessageReceivedEventHandler(WebView, *EventHandler)
Protected Result.i = #False
Protected Controller.ICoreWebView2Controller, Core.ICoreWebView2
Protected *WebMessageReceivedEventHandler.ICoreWebView2WebMessageReceivedEventHandler_Structure
Protected Token.q
If GadgetType(WebView) = #PB_GadgetType_WebView And *EventHandler <> #Null
Controller = GetGadgetAttribute(WebView, #PB_WebView_ICoreController)
If Controller
If Controller\get_CoreWebView2(@Core) = #S_OK
If Core
If FindMapElement(MapMessageReceivedEventHandler(), Str(WebView))
If MapMessageReceivedEventHandler()\Token
Core\remove_WebMessageReceived(MapMessageReceivedEventHandler()\Token)
EndIf
DeleteMapElement(MapMessageReceivedEventHandler())
EndIf
*WebMessageReceivedEventHandler = AddMapElement(MapMessageReceivedEventHandler(), Str(WebView))
If *WebMessageReceivedEventHandler
*WebMessageReceivedEventHandler\pVtbl = *WebMessageReceivedEventHandler + OffsetOf(IUnknownBase_Structure\pQueryInterface)
*WebMessageReceivedEventHandler\pQueryInterface = @ICoreWebView2WebMessageReceivedEventHandler_QueryInterface()
*WebMessageReceivedEventHandler\pAddRef = @ICoreWebView2WebMessageReceivedEventHandler_AddRef()
*WebMessageReceivedEventHandler\pRelease = @ICoreWebView2WebMessageReceivedEventHandler_Release()
*WebMessageReceivedEventHandler\pInvoke = @ICoreWebView2WebMessageReceivedEventHandler_Invoke()
*WebMessageReceivedEventHandler\pFunction = *EventHandler
If Core\add_WebMessageReceived(*WebMessageReceivedEventHandler, @*WebMessageReceivedEventHandler\Token) = #S_OK
;Debug *WebMessageReceivedEventHandler\Token
Result = #True
Else
DeleteMapElement(MapMessageReceivedEventHandler())
EndIf
EndIf
Core\Release()
EndIf
EndIf
EndIf
EndIf
ProcedureReturn Result
EndProcedure
;--------------------------------------
;- EXECUTESCRIPT WITH RESULTS RETURN
Procedure.l CoreWebView2ExecuteScriptCompletedHandler_Invoke(*this.ICoreWebView2ExecuteScriptCompletedHandler_Structure, errorCode.l, *returnObjectAsJson)
Protected sResult.s, iCount
;Debug "CoreWebView2ExecuteScriptCompletedHandler_Invoke"
If errorCode = #S_OK
If *returnObjectAsJson
*this\Result$ = PeekS(*returnObjectAsJson)
EndIf
EndIf
If *this\hEvent
SetEvent_(*this\hEvent)
EndIf
ProcedureReturn #S_OK
EndProcedure
Procedure.s WebViewExecuteScriptWithStringResult(WebView, JavaScript$)
Protected Result$
Protected Controller.ICoreWebView2Controller, Core.ICoreWebView2
Protected *ExecuteScriptCompletedHandler.ICoreWebView2ExecuteScriptCompletedHandler_Structure
Protected hEvent
If GadgetType(WebView) = #PB_GadgetType_WebView
Controller = GetGadgetAttribute(WebView, #PB_WebView_ICoreController)
If Controller
If Controller\get_CoreWebView2(@Core) = #S_OK And Core <> #Null
hEvent = CreateEvent_(0, 0, 0, 0)
If hEvent
*ExecuteScriptCompletedHandler = AllocateMemory(SizeOf(ICoreWebView2ExecuteScriptCompletedHandler_Structure))
If *ExecuteScriptCompletedHandler
*ExecuteScriptCompletedHandler\pVtbl = *ExecuteScriptCompletedHandler + OffsetOf(IUnknownBase_Structure\pQueryInterface)
*ExecuteScriptCompletedHandler\pQueryInterface = @ICoreWebView2NavigationCompletedEventHandler_QueryInterface()
*ExecuteScriptCompletedHandler\pAddRef = @ICoreWebView2NavigationCompletedEventHandler_AddRef()
*ExecuteScriptCompletedHandler\pRelease = @ICoreWebView2NavigationCompletedEventHandler_Release()
*ExecuteScriptCompletedHandler\pInvoke = @CoreWebView2ExecuteScriptCompletedHandler_Invoke()
*ExecuteScriptCompletedHandler\hEvent = hEvent
If Core\ExecuteScript(JavaScript$, *ExecuteScriptCompletedHandler) = #S_OK
While WaitForSingleObject_(hEvent, 0) <> #WAIT_OBJECT_0
WindowEvent()
Wend
Result$ = *ExecuteScriptCompletedHandler\Result$
EndIf
FreeMemory(*ExecuteScriptCompletedHandler)
EndIf
CloseHandle_(hEvent)
EndIf
Core\Release()
EndIf
EndIf
EndIf
ProcedureReturn Result$
EndProcedure
;--------------------------------------
#WebView_BusyTimer = 666
Global WebView2_Busy.b, WebView2_NaviComplete.b, WebView2_MessageChanged.b
Procedure ContentLoading(uri.s)
Debug "Loading: " + uri
WebView2_Busy = #True
EndProcedure
Procedure NaviComplete(uri.s)
Debug "Loaded: " + uri
WebView2_Busy = #False
WebView2_NaviComplete = #True
EndProcedure
Procedure ContentMessageChanged(uri.s)
Debug "message change: " + uri
WebView2_MessageChanged = #True
EndProcedure
Procedure MutationObserverSet(webView)
Protected javascript.s
javascript = "const observer = new MutationObserver((mutationsList) => {"
javascript + " for (let mutation of mutationsList) {"
javascript + " if (mutation.type === 'childList') {"
javascript + " console.log('A child node has been added or removed.');"
javascript + " } else if (mutation.type === 'attributes') {"
javascript + " console.log('The ' + mutation.attributeName + ' attribute was modified.');"
javascript + " }"
javascript + " }"
javascript + "});"
javascript + "observer.observe(document.body, { attributes: true, childList: true, subtree: true });"
javascript = "var observer = new MutationObserver(function(mutations) {"
javascript + " window.chrome.webview.postMessage('PBWEB content changed!');"
javascript + " });"
javascript + "observer.observe(document.body, { childList: true, subtree: true });"
Debug WebViewExecuteScriptWithStringResult(webView, javascript)
EndProcedure
;--------------------------------------
;- Creación de UI
OpenWindow(0, 0, 0, 1000, 900, "", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
StringGadget(0, 0, 0, 400, 30, "https://www.w3schools.com/xml/tryit.asp?filename=tryxml_parsertest2")
ButtonGadget(1, 410, 0, 50, 30, "Go")
WebViewGadget(2, 0, 35, 1000, 900, #PB_WebView_Debug)
WebViewSetContentLoadingEventHandler(2, @ContentLoading())
WebViewSetNavigateCompleteEventHandler(2, @NaviComplete())
AddWindowTimer(0, #WebView_BusyTimer, 100)
;--------------------------------------
;- EVENT LOOP
Repeat
Event = WaitWindowEvent()
If Event = #PB_Event_Timer
If EventTimer() = #WebView_BusyTimer
If WebView2_NaviComplete
WebView2_NaviComplete = #False
MutationObserverSet(2)
WebViewSetWebMessageReceivedEventHandler(2, @ContentMessageChanged())
Debug "complete!"
EndIf
If WebView2_Busy
Debug "WebView is Busy"
EndIf
If WebView2_MessageChanged
Debug "Message Changed!"
WebView2_MessageChanged = #False
EndIf
EndIf
EndIf
If Event = #PB_Event_Gadget
If EventGadget() = 1
SetGadgetText(2, Trim(GetGadgetText(0)))
EndIf
EndIf
Until Event = #PB_Event_CloseWindow
But I'm 200% sure that I'm doing something wrong, because I never get any result back from the debug console.
I've been guided by the following c# code, but it seems I'm not skilled enough to convert it properly
Code: Select all
using Microsoft.Web.WebView2.Core;
using Microsoft.Web.WebView2.WinForms;
using System;
using System.Windows.Forms;
public partial class Form1 : Form
{
private WebView2 webView;
public Form1()
{
InitializeComponent();
InitializeWebView();
}
private async void InitializeWebView()
{
webView = new WebView2();
webView.Dock = DockStyle.Fill;
this.Controls.Add(webView);
await webView.EnsureCoreWebView2Async(null);
// Navigate to the desired webpage
webView.CoreWebView2.Navigate("https://example.com");
// Inject JavaScript to monitor changes in the DOM
string script = @"
const observer = new MutationObserver((mutationsList) => {
for (let mutation of mutationsList) {
if (mutation.type === 'childList') {
console.log('A child node has been added or removed.');
} else if (mutation.type === 'attributes') {
console.log('The ' + mutation.attributeName + ' attribute was modified.');
}
}
});
observer.observe(document.body, { attributes: true, childList: true, subtree: true });
";
await webView.CoreWebView2.ExecuteScriptAsync(script);
// Handle JavaScript console messages
webView.CoreWebView2.WebMessageReceived += (sender, e) =>
{
// Output the console message to the C# console
Console.WriteLine(e.TryGetWebMessageAsString());
};
}
}
A (poorly) explanatory video:

Thank you very much for bothering to read me to the end!

Translated with DeepL.com (free version)