winforms 哪个WebView 2事件/函数可用于替换ScriptNotify Webview事件?

eh57zj3b  于 2022-11-17  发布在  其他
关注(0)|答案(2)|浏览(181)

今天,我决定在一个www.example.com应用程序中将WebView控件迁移到WebView2控件VB.net。
我已经从NuGet安装了WebView2,并且更改了声明和初始化行(在我的VB程序中只有4行,因为我使用的是2个WebView 2)。
当我构建我的应用程序时,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调用这个事件。

pkbketx9

pkbketx91#

使用WebView2处理事件通知的几种可能情况:
另请参阅:Use JavaScript in WebView for extended scenarios
一般初始化:

  • WebView 2示例的名称为myWebView2
  • 使用基本方法:例如,JSON反序列化是使用JavaScriptSerializer执行的。
  • 同样假定使用WinForms,您还没有指定GUI框架
Private Async Sub Load(sender As Object, e as EventArgs) Handles MyBase.Load
    await myWebView2.EnsureCoreWebView2Async(Nothing)
End Sub

此外,我还使用了这个简单的类模型,用于反序列化接收到的JSON消息,因为WebView2.WebMessageReceived采用JSON格式;但是您可以传递任何您想要的字符串。

Private Class JsonEventMessage
    Public Property Element As String
    Public Property Value As String
End Class

**1 -**在此方案中,JavaScript函数已在HTML中定义

  • 使用JSON.stringify()强调返回值是JSON对象
<!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()而不是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事件。加载文档时会引发此事件。我们需要此事件,因为在示例中,事件处理程序被添加到正文中的元素,而正文在此之前不可用。
NavigationCompleted中,我们可以将JavaScript Function添加到字符串中并调用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 -**这一次,HTML中的任何位置都没有定义JavaScript函数。

<!DOCTYPE html>
<html>
<head>
</head>
<body>
    <div id="div1">Some Text to Click</div>
</body>
</html>

案例1:

像以前一样订阅WebMessageReceivedNavigationCompleted事件。
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

案例2

订阅WebMessageReceivedWebView2.CoreWebView2InitializationCompleted
在本例中,我们向Document添加了一个事件侦听器,然后使用Event.Target成员和任何其他有助于处理通知的属性或值来确定单击了哪个Element。
这里,我只是将[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
kuarbcqp

kuarbcqp2#

我的问题现在解决了,我的解决方案如下...
我要显示以下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'>&#x2B60;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&#x2B60;</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'>&#x21E4;&#x22C6;</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的答案。

相关问题