哪个 WebView2 event/function 可以用来替换 ScriptNotify Webview 事件?
Which WebView2 event/function can be use to replace ScriptNotify Webview event?
今天,我决定在 VB.net 应用程序中将 WebView
控件迁移到 WebView2
控件。
我已经从 NuGet
安装了 WebView2
,并且更改了声明和初始化行(在我的 VB 程序中只有 4 行,因为我使用的是 2 个 WebView2)。
当我构建我的应用程序时,Visual Studio 2019
表明 ScriptNotify
事件不是 WebView2
的事件!
Private Sub wvSelect_ScriptNotify(
sender As Object,
e As WebViewControlScriptNotifyEventArgs) Handles wvSelect.ScriptNotify
使用旧的 WebView
控件,此事件是使用 windows.external.notify
Javascript 函数生成的。
function clickPlus(e) { window.external.notify("+PLUS:"); }
哪个事件正在替换 WebView2
控件中的 ScriptNotify
事件?
我很想知道新事件以及如何从 Javascript 调用此事件。
使用WebView2处理事件通知的几种可能情况:
另见:Use JavaScript in WebView for extended scenarios.
通用初始化:
- WebView2 实例名为
myWebView2
。
- 使用基本方法:例如,JSON 反序列化是使用JavaScriptSerializer 执行的。您可能有 Json.Net 或 System.Text.Json。
- 同样假设是 WinForms,您还没有指定 GUI 框架
Private Async Sub Load(sender As Object, e as EventArgs) Handles MyBase.Load
await myWebView2.EnsureCoreWebView2Async(Nothing)
End Sub
此外,我正在使用这个简单的 class 模型,用于反序列化收到的 JSON 消息,因为 WebView2.WebMessageReceived 假定 JSON 格式;不过,您可以传递任何您想要的字符串。
Private Class JsonEventMessage
Public Property Element As String
Public Property Value As String
End Class
1 - 在这种情况下,javascript 函数已在 HTML
中定义
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
function SomeFunction(e, v) {
var json = JSON.stringify({ Element:e.target.id, Value:v });
window.chrome.webview.postMessage(json);
}
</script>
</head>
<body>
<script>
document.getElementById("div1").addEventListener("click", function(e) {SomeFunction(e, '+PLUS:')});
</script>
<div id="div1">Some Text to Click</div>
</body>
</html>
在这种情况下,你只需要订阅WebMessageReceived
事件并反序列化JSON:
AddHandler myWebView2.WebMessageReceived, AddressOf myWebView2_WebMessageReceived
' [...]
Private Sub myWebView2_WebMessageReceived(sender As Object, e As CoreWebView2WebMessageReceivedEventArgs)
Dim message = New JavaScriptSerializer().Deserialize(Of JsonEventMessage)(e.TryGetWebMessageAsString())
Console.WriteLine(message.Element)
Console.WriteLine(message.Value)
End Sub
注意:我使用的是 e.TryGetWebMessageAsString() and not e.WebMessageAsJson,因为后者用引号引起来 (double-stringified)。当你传递一个简单的字符串时,它会更好地使用。
2 -这里在HEAD
中定义了一个JavaScript可以通知消息的函数,但其他地方没有添加事件处理程序。
假设您将在 运行 时间添加 HTML 元素,或者您不想在 HTML 或其他任何时间添加事件处理程序。
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
function SomeFunction(e, v) {
var json = JSON.stringify({ Element:e.target.id, Value:v });
window.chrome.webview.postMessage(json);
}
</script>
</head>
<body>
<div id="div1">Some Text to Click</div>
</body>
</html>
像以前一样订阅 WebMessageReceived
事件和 NavigationCompleted 事件。加载文档时会引发此事件。我们需要这个事件,因为在示例中,事件处理程序被添加到 Body 中的 Elements 中,这在此之前是不可用的。
在NavigationCompleted
中,我们可以将JavaScript函数添加到一个字符串中,调用WebView2.ExecuteScriptAsync()方法,在DOM就绪后执行脚本,否则GetElementById()
找不到目标。
AddHandler myWebView2.WebMessageReceived, AddressOf myWebView2_WebMessageReceived
AddHandler myWebView2.NavigationCompleted, AddressOf myWebView2_NavigationCompleted
' [...]
Private Sub myWebView2_WebMessageReceived(sender As Object, e As CoreWebView2WebMessageReceivedEventArgs)
Dim message = New JavaScriptSerializer().Deserialize(Of JsonEventMessage)(e.TryGetWebMessageAsString())
' [...]
End Sub
Private Async Sub myWebView2_NavigationCompleted(sender As Object, e As CoreWebView2NavigationCompletedEventArgs)
Dim func As String =
"document.getElementById('div1').
addEventListener('click', function(e) {
SomeFunction(e, '+PLUS:')
});"
Await myWebView2.ExecuteScriptAsync(func)
End Sub
3 - 这一次,没有 JavaScript 函数定义在 HTML.
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div id="div1">Some Text to Click</div>
</body>
</html>
案例一:
像以前一样订阅 WebMessageReceived
和 NavigationCompleted
事件。
在NavigationCompleted
中,发送消息的JavaScript函数被直接添加到事件处理程序中。调用 ExecuteScriptAsync()
执行脚本并将事件侦听器添加到 HTML 元素。
AddHandler myWebView2.WebMessageReceived, AddressOf myWebView2_WebMessageReceived
AddHandler myWebView2.NavigationCompleted, AddressOf myWebView2_NavigationCompleted
' [...]
Private Sub myWebView2_WebMessageReceived(sender As Object, e As CoreWebView2WebMessageReceivedEventArgs)
Dim message = New JavaScriptSerializer().Deserialize(Of JsonEventMessage)(e.TryGetWebMessageAsString())
' [...]
End Sub
Private Async Sub myWebView2_NavigationCompleted(sender As Object, e As CoreWebView2NavigationCompletedEventArgs)
Dim func As String =
"document.getElementById('div1').
addEventListener('click', function(e) {
var json = JSON.stringify({Element:e.target.id, Value:'+PLUS:'});
window.chrome.webview.postMessage(json);
});"
Await myWebView2.ExecuteScriptAsync(func)
End Sub
案例二:
订阅 WebMessageReceived
和 WebView2.CoreWebView2InitializationCompleted.
在这种情况下,我们向文档添加一个事件侦听器,然后使用 Event.Target
成员和任何其他可用于处理通知的 属性 或值来确定单击了哪个元素。
在这里,我只是将 [Event].target.id
和 [Event].target.innerText
作为 JSON 属性传递。您当然可以获得用例中所需的任何其他属性。
AddHandler myWebView2.WebMessageReceived, AddressOf myWebView2_WebMessageReceived
AddHandler myWebView2.CoreWebView2InitializationCompleted, AddressOf myWebView2_CoreWebView2InitializationCompleted
' [...]
Private Sub myWebView2_WebMessageReceived(sender As Object, e As CoreWebView2WebMessageReceivedEventArgs)
Dim message = New JavaScriptSerializer().
Deserialize(Of JsonEventMessage)(e.TryGetWebMessageAsString())
' [...]
End Sub
Private Async Sub myWebView2_CoreWebView2InitializationCompleted(
sender As Object,
e As CoreWebView2InitializationCompletedEventArgs)
Dim func as String =
"document.addEventListener
('click', function(e) {
window.chrome.webview.postMessage(
JSON.stringify({ Element:e.target.id, Value:e.target.innerText })
);
});"
Await myWebView2.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync(func)
End Sub
我的问题现在已经解决了,我的解决方案如下...
我想显示以下 HTML 页面
<div id="table">
<div id='Keyboard' class='panel'>
<div class='krow'>
<span class='k digit'>7</span>
<span class='k digit'>8</span>
<span class='k digit'>9</span>
<span class='k back'>⭠x</span>
</div>
<div class='krow'>
<span class='k digit'>4</span>
<span class='k digit'>5</span>
<span class='k digit'>6</span>
<span class='k delete'>x⭠</span>
</div>
<div class='krow'>
<span class='k digit'>1</span>
<span class='k digit'>2</span>
<span class='k digit'>3</span>
<span class='k clear'>⇤⋆</span>
</div>
<div class='krow'>
<span class='k empty'></span>
<span class='k digit'>0</span>
<span class='k point'>.</span>
<span class='k plus'><b>+</b></span>
</div>
</div>
</div>
为了在数字
上拦截 click
,我写了以下 Javascript 行
$(document).ready(function ()
{
$('.digit').click(function (ev) { clickDigit(ev); });
...
}
function clickDigit(e)
{
eDigit = e.target;
var sValue = eDigit.innerText;
window.chrome.webview.postMessage("+DIGIT:" + sValue);
}
如您所见,我调用 postMessage()
函数向 VB.Net 代码发送通知。
为了初始化和显示我的 HTML 代码,我写了以下几行
Private Sub Form_Load(sender As Object, e As EventArgs) Handles MyBase.Load
InitializeAsync()
End Sub
Async Sub InitializeAsync()
Await wvSelect.EnsureCoreWebView2Async()
wvSelect.NavigateToString(sHtmlText)
End Sub
其中 WebView2
控件在我的表单的设计器部分定义
Friend WithEvents wvSelect As Microsoft.Web.WebView2.WinForms.WebView2
最后,为了拦截JavaScript通知,我写了下面的VB.Net代码
Private Sub wvSelect_WebMessageReceived(sender As Object, e As CoreWebView2WebMessageReceivedEventArgs) _
Handles wvSelect.WebMessageReceived
Dim sValue As String = e.TryGetWebMessageAsString
Dim iPos = sValue.IndexOf(":")
Dim sAction = sValue.Substring(0, iPos)
sValue = sValue.Substring(iPos + 1)
Select Case sAction
Case "+DIGIT"
SendMessage(txtInput.Handle, WM_CHAR, AscW(sValue.Chars(0)), 0)
我希望我在此回答中报告的内容可以帮助其他用户并完成 Jimi
回答。
今天,我决定在 VB.net 应用程序中将 WebView
控件迁移到 WebView2
控件。
我已经从 NuGet
安装了 WebView2
,并且更改了声明和初始化行(在我的 VB 程序中只有 4 行,因为我使用的是 2 个 WebView2)。
当我构建我的应用程序时,Visual Studio 2019
表明 ScriptNotify
事件不是 WebView2
的事件!
Private Sub wvSelect_ScriptNotify(
sender As Object,
e As WebViewControlScriptNotifyEventArgs) Handles wvSelect.ScriptNotify
使用旧的 WebView
控件,此事件是使用 windows.external.notify
Javascript 函数生成的。
function clickPlus(e) { window.external.notify("+PLUS:"); }
哪个事件正在替换 WebView2
控件中的 ScriptNotify
事件?
我很想知道新事件以及如何从 Javascript 调用此事件。
使用WebView2处理事件通知的几种可能情况:
另见:Use JavaScript in WebView for extended scenarios.
通用初始化:
- WebView2 实例名为
myWebView2
。 - 使用基本方法:例如,JSON 反序列化是使用JavaScriptSerializer 执行的。您可能有 Json.Net 或 System.Text.Json。
- 同样假设是 WinForms,您还没有指定 GUI 框架
Private Async Sub Load(sender As Object, e as EventArgs) Handles MyBase.Load
await myWebView2.EnsureCoreWebView2Async(Nothing)
End Sub
此外,我正在使用这个简单的 class 模型,用于反序列化收到的 JSON 消息,因为 WebView2.WebMessageReceived 假定 JSON 格式;不过,您可以传递任何您想要的字符串。
Private Class JsonEventMessage
Public Property Element As String
Public Property Value As String
End Class
1 - 在这种情况下,javascript 函数已在 HTML
中定义<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
function SomeFunction(e, v) {
var json = JSON.stringify({ Element:e.target.id, Value:v });
window.chrome.webview.postMessage(json);
}
</script>
</head>
<body>
<script>
document.getElementById("div1").addEventListener("click", function(e) {SomeFunction(e, '+PLUS:')});
</script>
<div id="div1">Some Text to Click</div>
</body>
</html>
在这种情况下,你只需要订阅WebMessageReceived
事件并反序列化JSON:
AddHandler myWebView2.WebMessageReceived, AddressOf myWebView2_WebMessageReceived
' [...]
Private Sub myWebView2_WebMessageReceived(sender As Object, e As CoreWebView2WebMessageReceivedEventArgs)
Dim message = New JavaScriptSerializer().Deserialize(Of JsonEventMessage)(e.TryGetWebMessageAsString())
Console.WriteLine(message.Element)
Console.WriteLine(message.Value)
End Sub
注意:我使用的是 e.TryGetWebMessageAsString() and not e.WebMessageAsJson,因为后者用引号引起来 (double-stringified)。当你传递一个简单的字符串时,它会更好地使用。
2 -这里在HEAD
中定义了一个JavaScript可以通知消息的函数,但其他地方没有添加事件处理程序。
假设您将在 运行 时间添加 HTML 元素,或者您不想在 HTML 或其他任何时间添加事件处理程序。
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
function SomeFunction(e, v) {
var json = JSON.stringify({ Element:e.target.id, Value:v });
window.chrome.webview.postMessage(json);
}
</script>
</head>
<body>
<div id="div1">Some Text to Click</div>
</body>
</html>
像以前一样订阅 WebMessageReceived
事件和 NavigationCompleted 事件。加载文档时会引发此事件。我们需要这个事件,因为在示例中,事件处理程序被添加到 Body 中的 Elements 中,这在此之前是不可用的。
在NavigationCompleted
中,我们可以将JavaScript函数添加到一个字符串中,调用WebView2.ExecuteScriptAsync()方法,在DOM就绪后执行脚本,否则GetElementById()
找不到目标。
AddHandler myWebView2.WebMessageReceived, AddressOf myWebView2_WebMessageReceived
AddHandler myWebView2.NavigationCompleted, AddressOf myWebView2_NavigationCompleted
' [...]
Private Sub myWebView2_WebMessageReceived(sender As Object, e As CoreWebView2WebMessageReceivedEventArgs)
Dim message = New JavaScriptSerializer().Deserialize(Of JsonEventMessage)(e.TryGetWebMessageAsString())
' [...]
End Sub
Private Async Sub myWebView2_NavigationCompleted(sender As Object, e As CoreWebView2NavigationCompletedEventArgs)
Dim func As String =
"document.getElementById('div1').
addEventListener('click', function(e) {
SomeFunction(e, '+PLUS:')
});"
Await myWebView2.ExecuteScriptAsync(func)
End Sub
3 - 这一次,没有 JavaScript 函数定义在 HTML.
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div id="div1">Some Text to Click</div>
</body>
</html>
案例一:
像以前一样订阅 WebMessageReceived
和 NavigationCompleted
事件。
在NavigationCompleted
中,发送消息的JavaScript函数被直接添加到事件处理程序中。调用 ExecuteScriptAsync()
执行脚本并将事件侦听器添加到 HTML 元素。
AddHandler myWebView2.WebMessageReceived, AddressOf myWebView2_WebMessageReceived
AddHandler myWebView2.NavigationCompleted, AddressOf myWebView2_NavigationCompleted
' [...]
Private Sub myWebView2_WebMessageReceived(sender As Object, e As CoreWebView2WebMessageReceivedEventArgs)
Dim message = New JavaScriptSerializer().Deserialize(Of JsonEventMessage)(e.TryGetWebMessageAsString())
' [...]
End Sub
Private Async Sub myWebView2_NavigationCompleted(sender As Object, e As CoreWebView2NavigationCompletedEventArgs)
Dim func As String =
"document.getElementById('div1').
addEventListener('click', function(e) {
var json = JSON.stringify({Element:e.target.id, Value:'+PLUS:'});
window.chrome.webview.postMessage(json);
});"
Await myWebView2.ExecuteScriptAsync(func)
End Sub
案例二:
订阅 WebMessageReceived
和 WebView2.CoreWebView2InitializationCompleted.
在这种情况下,我们向文档添加一个事件侦听器,然后使用 Event.Target
成员和任何其他可用于处理通知的 属性 或值来确定单击了哪个元素。
在这里,我只是将 [Event].target.id
和 [Event].target.innerText
作为 JSON 属性传递。您当然可以获得用例中所需的任何其他属性。
AddHandler myWebView2.WebMessageReceived, AddressOf myWebView2_WebMessageReceived
AddHandler myWebView2.CoreWebView2InitializationCompleted, AddressOf myWebView2_CoreWebView2InitializationCompleted
' [...]
Private Sub myWebView2_WebMessageReceived(sender As Object, e As CoreWebView2WebMessageReceivedEventArgs)
Dim message = New JavaScriptSerializer().
Deserialize(Of JsonEventMessage)(e.TryGetWebMessageAsString())
' [...]
End Sub
Private Async Sub myWebView2_CoreWebView2InitializationCompleted(
sender As Object,
e As CoreWebView2InitializationCompletedEventArgs)
Dim func as String =
"document.addEventListener
('click', function(e) {
window.chrome.webview.postMessage(
JSON.stringify({ Element:e.target.id, Value:e.target.innerText })
);
});"
Await myWebView2.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync(func)
End Sub
我的问题现在已经解决了,我的解决方案如下...
我想显示以下 HTML 页面
<div id="table">
<div id='Keyboard' class='panel'>
<div class='krow'>
<span class='k digit'>7</span>
<span class='k digit'>8</span>
<span class='k digit'>9</span>
<span class='k back'>⭠x</span>
</div>
<div class='krow'>
<span class='k digit'>4</span>
<span class='k digit'>5</span>
<span class='k digit'>6</span>
<span class='k delete'>x⭠</span>
</div>
<div class='krow'>
<span class='k digit'>1</span>
<span class='k digit'>2</span>
<span class='k digit'>3</span>
<span class='k clear'>⇤⋆</span>
</div>
<div class='krow'>
<span class='k empty'></span>
<span class='k digit'>0</span>
<span class='k point'>.</span>
<span class='k plus'><b>+</b></span>
</div>
</div>
</div>
为了在数字
click
,我写了以下 Javascript 行
$(document).ready(function ()
{
$('.digit').click(function (ev) { clickDigit(ev); });
...
}
function clickDigit(e)
{
eDigit = e.target;
var sValue = eDigit.innerText;
window.chrome.webview.postMessage("+DIGIT:" + sValue);
}
如您所见,我调用 postMessage()
函数向 VB.Net 代码发送通知。
为了初始化和显示我的 HTML 代码,我写了以下几行
Private Sub Form_Load(sender As Object, e As EventArgs) Handles MyBase.Load
InitializeAsync()
End Sub
Async Sub InitializeAsync()
Await wvSelect.EnsureCoreWebView2Async()
wvSelect.NavigateToString(sHtmlText)
End Sub
其中 WebView2
控件在我的表单的设计器部分定义
Friend WithEvents wvSelect As Microsoft.Web.WebView2.WinForms.WebView2
最后,为了拦截JavaScript通知,我写了下面的VB.Net代码
Private Sub wvSelect_WebMessageReceived(sender As Object, e As CoreWebView2WebMessageReceivedEventArgs) _
Handles wvSelect.WebMessageReceived
Dim sValue As String = e.TryGetWebMessageAsString
Dim iPos = sValue.IndexOf(":")
Dim sAction = sValue.Substring(0, iPos)
sValue = sValue.Substring(iPos + 1)
Select Case sAction
Case "+DIGIT"
SendMessage(txtInput.Handle, WM_CHAR, AscW(sValue.Chars(0)), 0)
我希望我在此回答中报告的内容可以帮助其他用户并完成 Jimi
回答。