WebView2

Post your working scripts, libraries and tools.
20170201225639
Posts: 144
Joined: 01 Feb 2017, 22:57

Re: WebView2

Post by 20170201225639 » 20 Aug 2023, 08:38

Panaku wrote:
20 Aug 2023, 03:57
I've setup a couple of handlers for things such as NavigationCompleted and NavigationStarting, but I can't figure out how to pull the uri or url from the EventArgs. Could you maybe shed some light on this?
Panaku, is the Source property what you are looking for?

Code: Select all

Webview2Var := WebView2.create(GUIVar.Hwnd)
wvCoreVar := Webview2Var.CoreWebView2
wvCoreVar.add_NavigationCompleted(WebView2.Handler(NavigationCompleteHandler))
wvCoreVar.NavigateToString("....")
; ...
NavigationCompleteHandler(handler, ICoreWebView2, NavigationCompletedEventArgs){
	Msgbox wvCoreVar.Source
} 
EventArgs seems only to have 4 properties and none of them is URI/URL

https://learn.microsoft.com/en-us/dotnet/api/microsoft.web.webview2.core.corewebview2navigationcompletedeventargs?view=webview2-dotnet-1.0.1901.177

20170201225639
Posts: 144
Joined: 01 Feb 2017, 22:57

Re: WebView2

Post by 20170201225639 » 20 Aug 2023, 08:42

20170201225639 wrote:
19 Aug 2023, 17:35
Does anyone have a good solution for DOM manipulation?

....

To follow up, I suppose the answer is to use some kind of framework that can take care to avoid redrawing DOM. Here's a self-contained example using Vue. Speed-wise I'm pretty satisfied.

Code: Select all

#SingleInstance Force
#Include <WebView2\WebView2>
#Include <JSON>


NavStr := "
(
	<!DOCTYPE html>
	<html lang="en">

	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>Search Results Display</title>
		<!-- Include Vue via CDN -->
		<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
		<style>
				.results-wrapper {
				display: flex;
				flex-wrap: wrap;
				}

				.result-item {
				display: flex;
				border: 1px solid black;
				width: calc(20% - 2px); /* This will fit 5 divs per line, adjust as needed */
				margin: 1px;
				}

				.result-item div {
				flex: 1;
				padding: 5px;
				border-right: 1px solid black;
				}

				.result-item div:last-child {
				border-right: none;
				}
		</style>
	</head>

	<body>
		<div id="app">
			<div class="results-wrapper">
			    <div v-for="result in results" :key="result.id" class="result-item">
				  <div>{{ result.id }}</div>
				  <div>{{ result.name }}</div>
			    </div>
			</div>
		  </div>


		<script>
			let app = new Vue({
				el: '#app',
				data: {
					results: []
				}
			});


			function update_results() {
				(async function () {
					console.log("update_results");
					let str = await chrome.webview.hostObjects.AHK.getHostProperty("str");
					console.log(str);
					let obj = JSON.parse(str);
					app.results = obj

				})();
			}
		</script>
	</body>

	</html>
)"


GUIVar := Gui("+LastFound -Caption +AlwaysOnTop +ToolWindow")
GUIVar.Show(Format('w{} h{}', A_ScreenWidth * 0.6, A_ScreenHeight * 0.6))
Webview2Var := WebView2.create(GUIVar.Hwnd)
wvCoreVar := Webview2Var.CoreWebView2
HostObj := { str: "" }
wvCoreVar.add_NavigationCompleted(WebView2.Handler(NavHandler))
wvCoreVar.NavigateToString(NavStr)
wvCoreVar.AddHostObjectToScript("AHK", HostObj)

AllResults := []
Loop 10000
{
	id := A_Index
	name := Chr(Random(97, 122)) . Chr(Random(97, 122)) . Chr(Random(97, 122)) . Chr(Random(97, 122))
	AllResults.Push({ id: id, name: name },)
}


SendOneBatchOfRandomResults() {
	results := Array()
	AlreadyMap := Map()
	OneBatchLength := 100
	Loop
	{
		id := Random(1, 10000)
		if AlreadyMap.Has(id)
			continue
		if results.Length == OneBatchLength
			break
		AlreadyMap.Set(id, 1)
		results.Push(AllResults[id])
	}
	HostObj.str := JSON.stringify(results)
	wvCoreVar.ExecuteScript('update_results();', WebView2.Handler(ResultsHandler))
}

ResultsHandler(handler, errorCode, resultObjectAsJson) {
	static NumOfResultsSent := 1
	NumOfResultsSent++
	Sleep(50)
	if (NumOfResultsSent > 100)
		return
	else
		SendOneBatchOfRandomResults()
}


NavHandler(handler, ICoreWebView2, NavigationCompletedEventArgs) {
	SendOneBatchOfRandomResults()
}


^k::
{
	ExitApp()
}

Panaku
Posts: 22
Joined: 02 Apr 2022, 17:24

Re: WebView2

Post by Panaku » 20 Aug 2023, 13:36

20170201225639 wrote:
20 Aug 2023, 08:38
Panaku wrote:
20 Aug 2023, 03:57
I've setup a couple of handlers for things such as NavigationCompleted and NavigationStarting, but I can't figure out how to pull the uri or url from the EventArgs. Could you maybe shed some light on this?
Panaku, is the Source property what you are looking for?

Code: Select all

Webview2Var := WebView2.create(GUIVar.Hwnd)
wvCoreVar := Webview2Var.CoreWebView2
wvCoreVar.add_NavigationCompleted(WebView2.Handler(NavigationCompleteHandler))
wvCoreVar.NavigateToString("....")
; ...
NavigationCompleteHandler(handler, ICoreWebView2, NavigationCompletedEventArgs){
	Msgbox wvCoreVar.Source
} 
EventArgs seems only to have 4 properties and none of them is URI/URL

https://learn.microsoft.com/en-us/dotnet/api/microsoft.web.webview2.core.corewebview2navigationcompletedeventargs?view=webview2-dotnet-1.0.1901.177
NavigationStartingEventArgs includes the Uri

https://learn.microsoft.com/en-us/dotnet/api/microsoft.web.webview2.core.corewebview2navigationstartingeventargs?view=webview2-dotnet-1.0.1901.177

User avatar
thqby
Posts: 431
Joined: 16 Apr 2021, 11:18
Contact:

Re: WebView2

Post by thqby » 21 Aug 2023, 03:45

Code: Select all

XXXHandler(handler, ICoreWebView2, XXXEventArgs){
	wv := WebView2.Core(ICoreWebView2)
	args_obj := Webview2.XXXEventArgs(XXXEventArgs)
}
You can refer to the template above to wrap eventargs pointers as objects.
@Panaku

Panaku
Posts: 22
Joined: 02 Apr 2022, 17:24

Re: WebView2

Post by Panaku » 26 Aug 2023, 11:18

@thqby Do you know how I can determine which WebView an event is coming from?
I've parsed out all the information I seem to be able from the ICoreWebView2 and EventArgs, but none of it works as an unique identifier.

Code: Select all

BrowserProcessId: 3240
CanGoBack: 0
CanGoForward: 0
ContainsFullScreenElement: 0
DefaultDownloadDialogCornerAlignment: 1
DefaultDownloadDialogMargin: 42949672990
DocumentTitle: 
BrowserVersionString: 115.0.1901.203
FailureReportFolderPath: C:\Users\<redacted>\AppData\Local\Microsoft\Edge\User Data\EBWebView\Crashpad\reports
UserDataFolder: C:\Users\<redacted>\AppData\Local\Microsoft\Edge\User Data
FaviconUri: 
IsDefaultDownloadDialogOpen: 0
IsDocumentPlayingAudio: 0
IsMuted: 0
IsSuspended: 0
MemoryUsageTargetLevel: 0
AreBrowserAcceleratorKeysEnabled: 1
AreDefaultContextMenusEnabled: 1
AreDefaultScriptDialogsEnabled: 1
AreDevToolsEnabled: 1
AreHostObjectsAllowed: 1
HiddenPdfToolbarItems: 0
IsBuiltInErrorPageEnabled: 1
IsGeneralAutofillEnabled: 1
IsPasswordAutosaveEnabled: 0
IsPinchZoomEnabled: 1
IsReputationCheckingRequired: 1
IsScriptEnabled: 1
IsStatusBarEnabled: 1
IsSwipeNavigationEnabled: 1
IsWebMessageEnabled: 1
IsZoomControlEnabled: 1
UserAgent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36 Edg/115.0.1901.203
Source: about:blank
StatusBarText: 
AdditionalAllowedFrameAncestors: 
Cancel: 0
IsRedirected: 0
IsUserInitiated: 0
NavigationId: 2
Uri: <redacted>
I tried to add add some AdditionalBrowserArguments to the EnvironmentOptions but the class returns an error.

Code: Select all

wvc := WebView2.create(this.gui.Hwnd,,,,,{AdditionalBrowserArguments: "--window-name='test'"})
I was able to override the Settings.UserAgent information, which I could definitely use as a unique identifier, but that's just messy and of course if I need the actual UserAgent information for anything it'll be gone.

I also tried just pulling the ParentWindow from the ICoreWebView2 passed to the handler, but the ParentWindow comes from the controller, and I couldn't seem to find a way to access controller information from it.

Panaku
Posts: 22
Joined: 02 Apr 2022, 17:24

Re: WebView2

Post by Panaku » 30 Aug 2023, 20:43

Looking at your example from another post on this thread, I know that I'm attempting to add AdditionalBrowserArguments as you intended but it keeps generating an error. The error it gives is

Code: Select all

Error: This value of type "Integer" has no property named "TargetCompatibleBrowserVersion"
and is occurring on line #857 of the WebView2.ahk file. I haven't assigned a value to TargetCompatibleBrowserVersion myself, it looks like that's being force assigned at line #39. I tried enumerating over all the properties for the options at the

Code: Select all

get_xxx_str(prop, this, pvalue)
function at line #855, and I can see where the options are being properly passed to this function but the

Code: Select all

this
item doesn't have any properties. I even tried to manually pull the property name and value during this function and assign it but received this error:

Code: Select all

Error: This value of type "Integer" has no method named "DefineProp"
. I seem unable to figure out how to fix the issue in the library.

User avatar
thqby
Posts: 431
Joined: 16 Apr 2021, 11:18
Contact:

Re: WebView2

Post by thqby » 30 Aug 2023, 22:42

Panaku wrote:
30 Aug 2023, 20:43
Looking at your example from another post on this thread, I know that I'm attempting to add AdditionalBrowserArguments as you intended but it keeps generating an error. The error it gives is

Code: Select all

Error: This value of type "Integer" has no property named "TargetCompatibleBrowserVersion"
There is a typo, pm := DllCall('ole32\CoTaskMemAlloc', 'uptr', s := StrLen(v := opts.%prop%) * 2 + 2, 'ptr').
Panaku wrote: I've parsed out all the information I seem to be able from the ICoreWebView2 and EventArgs, but none of it works as an unique identifier.
The ptr of ICoreWebView2.

Panaku
Posts: 22
Joined: 02 Apr 2022, 17:24

Re: WebView2

Post by Panaku » 31 Aug 2023, 18:39

There is a typo, pm := DllCall('ole32\CoTaskMemAlloc', 'uptr', s := StrLen(v := opts.%prop%) * 2 + 2, 'ptr').
Correcting this typo allowed the script to move forward to the next part of creating the WebView2 but now produces an error at line #46. throw OSError(R) returns

Code: Select all

Error: (0x80070057) The parameter is incorrect.
Which is an operating system error and not an AHK error specifically, but after looking into the error and going through several general solutions (not related to this script) I was unable to get past this error either.

I looked into the CreateCoreWebView2EnvironmentWithOptions function of the WebView2Loader.dll and from what I found all the parameters being passed in the DllCall seem correct, so I'm not sure where the hang up is occurring.

The ptr of ICoreWebView2.
I guess I'm just too inexperienced/uneducated with matters like this because I still wasn't able to find a comparison between the my created wv/wvc and the ICoreWebView2. I tried comparing several pieces of information including the ICoreWebView2, StrGet(ICoreWebView2), StrPtr(StrGet(ICoreWebView2), and even NumGet(ICoreWebView2, "ptr") but nothing matched anything I was able to derive from my defined wv or wvc.

User avatar
thqby
Posts: 431
Joined: 16 Apr 2021, 11:18
Contact:

Re: WebView2

Post by thqby » 01 Sep 2023, 08:23

Panaku wrote:
31 Aug 2023, 18:39
Correcting this typo allowed the script to move forward to the next part of creating the WebView2 but now produces an error at line #46. throw OSError(R) returns

Code: Select all

Error: (0x80070057) The parameter is incorrect.
Which is an operating system error and not an AHK error specifically, but after looking into the error and going through several general solutions (not related to this script) I was unable to get past this error either.
Fixed by 3bf8931

In this library, each webview2 object has ptr properties, which are unique. Some events will have an ICoreWebView2 parameter, You can store ICoreWebView2's ptr and WebView2.Core objects with maps, retrieve existing WebView2.Core objects when ICoreWebView2's ptr is obtained, otherwise wrap and store it cache[ICoreWebView2] := WebView2.Core(ICoreWebView2)
But remember to release them when you don't need them.

Code: Select all

wvc := WebView2.create(this.gui.Hwnd,,,,,{AdditionalBrowserArguments: "--window-name='test'"})
MsgBox wvc.ptr ' ' wvc.CoreWebView2.ptr

Tre4shunter
Posts: 139
Joined: 26 Jan 2016, 16:05

Re: WebView2

Post by Tre4shunter » 18 Sep 2023, 08:56

Any ideas if there was a change within the Webview2? All of my apps that use the printtopdf function now cut off the page when printing. The only print settings im using aside from default are setting background images and portrait mode.

This has blown up like half of my apps - bit stuck what to do here.

[EDIT] - for now i ended up changing the print scaling to .7? Which works...but i have no idea why i need to do this now.

Thanks!

-Tre4

Panaku
Posts: 22
Joined: 02 Apr 2022, 17:24

Re: WebView2

Post by Panaku » 02 Dec 2023, 08:49

Once again, my ignorance knows no bounds. I'm trying to set up some event handlers, and running into some trouble. Any handlers that are part of the Controller or Core classes I'm able to setup, but I'm having issues with the other classes.

Here's examples of what I've got going on

Code: Select all

wvc := WebView2.create(this.gui.Hwnd) ;Working
wv := wvc.CoreWebView2 ;Working
dlo := WebView2.DownloadOperation ;Seems to work

GotFocusHandler := wvc.GotFocus(myTestFunc) ;Working
NavigationStartingHandler := wv.NavigationStarting(myTestFunc2) ;Working
BytesReceivedChangedHandler := dlo.BytesReceivedChanged(myTestFunc3) ;Produces an error
Error: This value of type "Class" has no method named "BytesReceivedChanged".

Can you help me understand how I can set up event handlers for the events that are apart of the other classes that aren't the controller or core?

Panaku
Posts: 22
Joined: 02 Apr 2022, 17:24

Re: WebView2

Post by Panaku » 04 Dec 2023, 01:50

To follow up on the issue with accessing the nested classes:
I am getting some errors with the ComCalls. I still don't know the right way to access the nested classes, but I did find that I was able to do so from within the Create method of the main class by doing the following

Code: Select all

dlo := this.DownloadOperation()
testUri := dlo.Uri
This produces the following two errors.
image.png
image.png (19.41 KiB) Viewed 1716 times
image.png
image.png (18.23 KiB) Viewed 1716 times

User avatar
thqby
Posts: 431
Joined: 16 Apr 2021, 11:18
Contact:

Re: WebView2

Post by thqby » 04 Dec 2023, 06:21

You should get the instance of DownloadOperation from the parameters of DownloadStartingEvent. Therefore, you can only invoke a DownloadOperation object within a DownloadStarting event.

Code: Select all

g := Gui()
g.Show('w800 h600')
wvc := WebView2.create(g.Hwnd)
wv := wvc.CoreWebView2
wv.Navigate('https://www.autohotkey.com/download/2.1/AutoHotkey_2.1-alpha.7_setup.exe.sha256')
ds := wv.DownloadStarting(DownloadStartingHandler)
DownloadStartingHandler(handle, wv, args) {
	wv := WebView2.Core(wv)
	args := WebView2.DownloadStartingEventArgs(args)
	downloadOperation := args.DownloadOperation
	; ...
}

Panaku
Posts: 22
Joined: 02 Apr 2022, 17:24

Re: WebView2

Post by Panaku » 04 Dec 2023, 18:27

So if we only access the DownloadOperation object from within the DownloadStarting event, are we able to (and do we need to) create an event handler for the events that are a part of the DownloadOperation object?

I'm trying to figure out how to create callback handlers for each event in the class but I'm having issues with items like this.

User avatar
thqby
Posts: 431
Joined: 16 Apr 2021, 11:18
Contact:

Re: WebView2

Post by thqby » 05 Dec 2023, 08:54

Panaku wrote:
04 Dec 2023, 18:27
So if we only access the DownloadOperation object from within the DownloadStarting event, are we able to (and do we need to) create an event handler for the events that are a part of the DownloadOperation object?
Of course, if you need it.
I'm also not sure that these objects could possibly be used outside of events.

bonobo
Posts: 76
Joined: 03 Sep 2023, 20:13

Re: WebView2

Post by bonobo » 08 Dec 2023, 16:30

Has anyone been able to get WinSetTransColor to play nice with Webview2, so mouse events (clicking, hovering) over the non-transparent part of the page doesn't simply fall through?

To illustarte, if I run this

Code: Select all

MyGui := Gui('+AlwaysOnTop')
MyGui.BackColor := "F0F0F0"
MyGui.OnEvent('Close', (*) => (wvc := wv := 0))
MyGui.Show(Format('w{} h{}', A_ScreenWidth * 0.5, A_ScreenHeight * 0.5))
wvc := WebView2.create(MyGui.Hwnd)
wv := wvc.CoreWebView2
wv.NavigateToString('<html><head><style>.square{width: 100px; height: 100px; background: red; margin: auto; font-size: 2em} .square:hover{zoom: 2} body {display:flex;}</style></head><body><div class=square>hover me</div></body></html>')
I get a non-transparent page (with gray background), and if I hover over the red square the red square will double in size. So far, so good.
image.png
image.png (512.8 KiB) Viewed 1487 times
But I want to make everything except the red square transparent. And this I can do by adding this line

Code: Select all

MyGui := Gui('+AlwaysOnTop')
MyGui.BackColor := "F0F0F0"
MyGui.OnEvent('Close', (*) => (wvc := wv := 0))
WinSetTransColor(MyGui.BackColor, MyGui) ; 👈👈👈
MyGui.Show(Format('w{} h{}', A_ScreenWidth * 0.5, A_ScreenHeight * 0.5))
wvc := WebView2.create(MyGui.Hwnd)
wv := wvc.CoreWebView2
wv.NavigateToString('<html><head><style>.square{width: 100px; height: 100px; background: red; margin: auto; font-size: 2em} .square:hover{zoom: 2} body {display:flex;}</style></head><body><div class=square>hover me</div></body></html>')
Now when I run this code, there's only the red square showing on the screen.
image.png
image.png (1.69 MiB) Viewed 1487 times
However, if I click or hover on the red square, nothing happens, and the mouse events simply fall through to whatever window is behind it. But that's not how WinSetTransColor normally works: normally, if the user clicks on a pixel made transparent by WinSetTransColor, the click will fall through, but if the user clicks on a visible pixel, the click will be captured by the window.

User avatar
thqby
Posts: 431
Joined: 16 Apr 2021, 11:18
Contact:

Re: WebView2

Post by thqby » 10 Dec 2023, 01:27

@bonobo
viewtopic.php?p=534804#p534804

set DefaultBackgroundColor of webview2.

neogna2
Posts: 598
Joined: 15 Sep 2016, 15:44

Re: WebView2

Post by neogna2 » 07 Feb 2024, 16:28

thqby, at WebView2.ahk#L7 you have a comment that targets a WebView2 package version, currently it says "@webview2version 1.0.2151.40".

Should that be interpreted as "use this or more recent version" or "use exactly this version"?

In other words, could there be some incompatibility or other issue with using your WebView2.ahk with the latest WebView2 prerelease package from Microsoft?

User avatar
thqby
Posts: 431
Joined: 16 Apr 2021, 11:18
Contact:

Re: WebView2

Post by thqby » 12 Feb 2024, 06:18

Generally, only interfaces and methods are added after the upgrade, and only one method name is changed once.
The version in the file may be higher than the dll version because I did not update the dll file.

jsong55
Posts: 256
Joined: 30 Mar 2021, 22:02

Re: WebView2

Post by jsong55 » 04 Mar 2024, 09:47

I get failed to load DLL error, even if I pass the full path to the last param on create.

Using Win 11

Also couldn't find much tutorial

Can someone guide me how to pass my form data collected by JS on single page html to main ahk script. How to add the listener or callback?

Post Reply

Return to “Scripts and Functions (v2)”