【问题标题】:Call a WinForm procedure from embedded Cefsharp browser从嵌入式 Cefsharp 浏览器调用 WinForm 过程
【发布时间】:2018-03-16 11:02:34
【问题描述】:

我正在创建一个 WinForm 应用程序,其中包含一个嵌入式浏览器,它借助 Leaflet 框架显示 OSM 地图。在 WinForm 端有图表,必须根据用户在 OSM 地图上选择的标记进行更新。只要我在 Visual Studio 中使用原生浏览器,浏览器和 winform 的交互就运行良好。但由于 IE 中大量标记的渲染效果不佳,我不得不在 Cefsharp 的帮助下切换到 Chromium。

我使用的 Cefsharp 版本是 3.3239.1723.g071d1c1。部署浏览器没有任何问题(ChrisKent 教程帮助很大 - link)。

我面临的主要问题是如何在 Cefsharp/Chromium 浏览器中从 JS 调用 Winform 过程。

在 VS 中使用本机浏览器控件时,这可以很容易地完成,但我想在 Cefsharp 中方法完全不同。我在网上阅读文档和一些可用的问题,但我找不到我的答案。可能我需要根据文档向 JavaScript 公开一个 .NET 类。老实说,我不明白该怎么做。最重要的是,我正在使用 Visual Basic。

任何帮助将不胜感激。下面我可以非常简化地展示我需要的东西。 JavaScript onClick 事件应该触发 WinForms HelloWorld() 过程的执行。

//JavaScript side
<script>
    function onClick(e) {
       //How to Call Winform sub HelloWorld?
       //with native browser this is done with "window.external.HelloWorld();"
    };

WinForm 如下所示:

Imports CefSharp.WinForms
Imports CefSharp

Public Class Form1

Private WithEvents browser As ChromiumWebBrowser

Public Sub New()
    InitializeComponent()

    Dim settings As New CefSettings()
    CefSharp.Cef.Initialize(settings)

    browser = New ChromiumWebBrowser("http://localhost") With {
    .Dock = DockStyle.Fill
    }
    panBrowser.Controls.Add(browser)

End Sub

Private Sub HelloWorld()

    MsgBox("Hello World")

End Sub

End Class

提前谢谢你!

【问题讨论】:

  • github.com/cefsharp/CefSharp/wiki/…github.com/cefsharp/CefSharp/issues/2246 文档将很快更新,在此之前您必须将其拼凑起来。 VB.Net中没有官方的例子。
  • 感谢@amaitland 指出有一种新的绑定方法。我做了一些研究,发现了如何实现我所需要的。我会将其发布为对我的问题的自我回答。 Cefsharp 项目真的很棒 :) 并为你对它的贡献欢呼!

标签: javascript winforms chromium cefsharp


【解决方案1】:

在 amaitland 在 cmets 中指出我在最新版本的 Cefsharp 中有一种新的绑定方法之后,我进行了一些额外的研究并找到了解决我的问题的方法。下面是从嵌入式 Cefsharp 浏览器中运行的 JavaScript 调用 VB 过程“showMessage”的代码。此过程将从 JS 传递的字符串值写入 Winform 中的 TextBox。希望这对某人有所帮助。

JavaScript 端

function onClick(e) {

    var popup = e.target.getPopup();
    var content = popup.getContent();

    // calling starts here
    (async function() {
    await CefSharp.BindObjectAsync("boundAsync", "bound");
    // "showMessage" is the VB procedure to call in a class "boundAsync"
    boundAsync.showMessage(content);
})();
    // calling ends here

};

VB端

Imports CefSharp.WinForms
Imports CefSharp

Public Class Form1

Private WithEvents browser As ChromiumWebBrowser

// row below is needed for communication between the new class and Form1
Friend Shared MyInstance As Form1

    Public Sub New()
        InitializeComponent()

        Dim settings As New CefSettings()
        CefSharp.Cef.Initialize(settings)

        browser = New ChromiumWebBrowser("localhost") With {
        .Dock = DockStyle.Fill
        }

        panBrowser.Controls.Add(browser)
        // add this line for registering a new class boundAsync
        browser.JavascriptObjectRepository.Register("boundAsync", New BoundObject(), True)

    End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        // row below is needed for communication between the new class and Form1
        MyInstance = Me

    End Sub

End Class

// declare the new class
Public Class BoundObject

    // declare the procedure called by JS
    // in this example a value passed from JS is assigned to a TextBox1 on Form1
    Public Sub showMessage(ByVal msg As String)

        If (Form1.MyInstance IsNot Nothing) AndAlso Not Form1.MyInstance.IsDisposed Then

            If Form1.MyInstance.TextBox1.InvokeRequired Then
                Form1.MyInstance.TextBox1.Invoke(New Action(Of String)(AddressOf showMessage), msg)
            Else
                Form1.MyInstance.TextBox1.Text = msg
            End If

        End If

    End Sub
End Class

【讨论】:

  • 您还试图绑定一个名为 bound 的对象,这可能只是一个复制和粘贴错误。如果您只是从事件处理程序访问对象,那么您可能可以将其注册到标头中的 J 块中,而不必担心等待绑定完成。
  • 在某些时候我可能会添加一个帮助方法来注册事件,它可能看起来像 gist.github.com/amaitland/48adad9c7f2c57f6c17fad39b2747d00 不太适合您的用例,只是作为参考发布。
猜你喜欢
  • 2022-11-02
  • 1970-01-01
  • 2013-08-02
  • 1970-01-01
  • 2017-09-13
  • 2012-04-13
  • 1970-01-01
  • 2023-03-10
  • 1970-01-01
相关资源
最近更新 更多