【问题标题】:Use Blockly inside a WPF WebBrowser在 WPF WebBrowser 中使用 Blockly
【发布时间】:2016-11-25 07:44:04
【问题描述】:

是否可以在 WPF WebBrowser 中使用 Blockly google javascript 库?

特别是,Blockly 需要several js scripts。 js库如何引用?

【问题讨论】:

  • WPF WebBrowser 是一个嵌入式Internet Explorer,因此它可以完美地使用外部脚本。你试过了吗?有什么问题吗?
  • 好吧,使用 InvokeScript 方法似乎可以使用外部简单的 Javascript 函数。我的问题是要知道如何使用像 Blockly 这样的 Javascript 库,它需要多个脚本声明、参数配置和工作空间注入。
  • 只需在developers.google.com/blockly/guides/get-started/web 的示例代码中引用 demos/fixed/index.html 并将您的 webbrowser Source 属性指向它。请注意,您必须在 WebBrowser 中打开 IE11 仿真,如下所述:blog.malwarebytes.com/101/2016/01/… 使用您的 .exe 文件的名称
  • 感谢您的帮助!我设法在 WebBrowser 中调用 index.html 页面。但是现在我怎样才能使用通过这个 WebBrowser 的 Blockly API 呢?
  • 这个问题太笼统了。是的,你可以使用它。你想让我做什么?多个.js 文件有什么问题。只需在 head 标签中引用它们并使用它们。

标签: javascript c# wpf webbrowser-control blockly


【解决方案1】:

简答

您可以使用 WPF WebBrowser 控件中的所有块状功能,包括 UI 工具和 API 函数。为此,您应该:

  • 创建一个 HTML 内容,其中包含引用 Blocky jsscript 标记,或您想从 C# 调用的方法,以及根据您的要求(例如工具箱和工作区)所需的 HTML 和 XML 内容。您可以在运行时动态加载工具箱和工作区。
  • 使用NavigateNavigateToString将内容加载到WebBrowser控件
  • 如果您需要调用脚本,请使用WebBrowser 控件的InvokeScript 方法。

另外,为了能够使用Blocky,您应该使WebBrowser 使用最新的文档模式而不使用兼容模式并显示现代内容。


示例

这个例子显示:

  • 如何动态加载工具箱
  • 如何动态加载工作区
  • 如何使用 javascript 方法调用 Blocky API 方法。在示例中,您可以看到 showCoderunCode 代理方法,它们独立于 wprkspace 并且适用于任何工作空间。您可以从 C# 调用 javascript 方法。

例如,您可以使用Blocky Demos 中的任何一个。我创建了一个示例,展示了使用 Blocky API 方法和 Blocky UI 工具。此示例基于Generating Javascript 示例,该示例展示了如何使用 Blocky API 从 Blocky 工作区生成 javascript。

下载

您可以从以下位置克隆或下载工作示例:

逐步创建示例

该示例包含一个简单的 HTML 文件,在其 head 标签中添加了所需的 javascript 文件。它还包含两个我们创建的从 C# 调用的代理方法。

该示例还包含两个 xml 文件。为 Blocky 工作区打开,为工具箱打开一个。

注意:创建这些文件不是强制性的,您可以在运行时动态创建工作区或工具箱。这只是为了表明您可以在运行时加载工作区和工具箱,它们不需要是静态的。

1) 创建 WPF 应用程序

创建一个 WPF 项目并将其命名为 WpfAppllicatin1

2) 创建blockyWorkspace.xml 文件

使用以下内容创建blockyWorkspace.xml 文件。该文件将用于创建 Blocky 工作区。

<xml>
<block type="controls_if" inline="false" x="20" y="20">
    <mutation else="1"></mutation>
    <value name="IF0">
    <block type="logic_compare" inline="true">
        <field name="OP">EQ</field>
        <value name="A">
        <block type="math_arithmetic" inline="true">
            <field name="OP">ADD</field>
            <value name="A">
            <block type="math_number">
                <field name="NUM">6</field>
            </block>
            </value>
            <value name="B">
            <block type="math_number">
                <field name="NUM">7</field>
            </block>
            </value>
        </block>
        </value>
        <value name="B">
        <block type="math_number">
            <field name="NUM">13</field>
        </block>
        </value>
    </block>
    </value>
    <statement name="DO0">
    <block type="text_print" inline="false">
        <value name="TEXT">
        <block type="text">
            <field name="TEXT">Don't panic</field>
        </block>
        </value>
    </block>
    </statement>
    <statement name="ELSE">
    <block type="text_print" inline="false">
        <value name="TEXT">
        <block type="text">
            <field name="TEXT">Panic</field>
        </block>
        </value>
    </block>
    </statement>
</block>
</xml>

3) 创建blockyToolbox.xml 文件

使用以下内容创建blockyToolbox.xml 文件。该文件将用于创建 Blocky 工具箱。

<xml>
    <block type="controls_if"></block>
    <block type="logic_compare"></block>
    <block type="controls_repeat_ext"></block>
    <block type="math_number"></block>
    <block type="math_arithmetic"></block>
    <block type="text"></block>
    <block type="text_print"></block>
</xml>

4) 创建blockyHTML.html 文件

使用以下内容创建blockyHTML.html 文件。该文件仅包含对 Blocky 脚本的引用以及我们的 javascript 方法,这些方法将使用 C# 代码从我们的应用程序中调用:

<html>
<head>
  <meta http-equiv="X-UA-Compatible" content="IE=10" />
  <script src="https://blockly-demo.appspot.com/static/blockly_compressed.js"></script>
  <script src="https://blockly-demo.appspot.com/static/blocks_compressed.js"></script>
  <script src="https://blockly-demo.appspot.com/static/javascript_compressed.js"></script>
  <script src="https://blockly-demo.appspot.com/static/msg/js/en.js"></script>
</head>
<body>
    <div id="host" style="height: 480px; width: 600px;"></div>
    <script>
        var workspace;
        function init(toolboxXML, workspaceXML) {
            workspace = Blockly.inject('host',
            { media: '../../media/', toolbox: toolboxXML });
            var wx = Blockly.Xml.textToDom(workspaceXML)
            Blockly.Xml.domToWorkspace(wx, workspace);
        }
        function showCode() {
            Blockly.JavaScript.INFINITE_LOOP_TRAP = null;
            var code = Blockly.JavaScript.workspaceToCode(workspace);
            return code;
        }
        function runCode() {
            window.LoopTrap = 1000;
            Blockly.JavaScript.INFINITE_LOOP_TRAP =
                'if (--window.LoopTrap == 0) throw "Infinite loop.";\n';
            var code = Blockly.JavaScript.workspaceToCode(workspace);
            Blockly.JavaScript.INFINITE_LOOP_TRAP = null;
            try { eval(code); } catch (e) { alert(e); }
        }
    </script>
</body>
</html>

5) 编写 C# 代码

放置一个WebBrowser 控件并将其命名为browser 并处理其LoadCompleted 事件。还要在窗口上放置两个Button 控件并将它们命名为showCodeButtonrunCodeButton 并像这样处理它们的Click 事件:

public MainWindow()
{
    InitializeComponent();
    showCodeButton.IsEnabled = false;
    runCodeButton.IsEnabled = false;
    browser.NavigateToString(System.IO.File.ReadAllText(@"d:\blockyHTML.html"));
}
private void browser_LoadCompleted(object sender, NavigationEventArgs e)
{
    showCodeButton.IsEnabled = true;
    runCodeButton.IsEnabled = true;
    var toolboxXML = System.IO.File.ReadAllText(@"d:\blockyToolbox.xml");
    var workspaceXML = System.IO.File.ReadAllText(@"d:\blockyWorkspace.xml");
    //Initialize blocky using toolbox and workspace
    browser.InvokeScript("init", new object[] { toolboxXML, workspaceXML });
}
private void showCodeButton_Click(object sender, RoutedEventArgs e)
{
    var result = browser.InvokeScript("showCode", new object[] { });
    MessageBox.Show(result.ToString());
}
private void runCodeButton_Click(object sender, RoutedEventArgs e)
{
    browser.InvokeScript("runCode", new object[] { });
}

6) 运行应用程序

当您运行应用程序时,在启用按钮后,单击第一个按钮,然后您可以得到 showCode 方法的结果,该方法使用块 API 从块工作区生成 javascript 代码。

您还可以通过单击第二个按钮来运行您使用 blocky 创建的代码。

【讨论】:

  • 1) 您可以在 HTML 文件中包含 Blocky 工作区,就像 Blocky 的大多数演示示例一样。我使用了一个不同的文件来展示如何注入工作区。如果要使用 Blocky 的 UI 工具,只需在同一个 html 文件(甚至是单独的文件)中创建工具箱和工作区,并将 HTML 文件加载到WebBrowser 控件中即可。
  • 2) 直接调用 Blocky API 函数是可能的,但是由于方法可能需要一些上下文并且您可能需要在单个上下文中调用多个方法以获得所需的结果,所以我相信创建一个为您执行此类任务的单一 JavaScript 界面会更加友好。
  • @SunnyBhadana 在回答问题时,我试过了,它运行良好,屏幕截图来自工作实例。我猜您在 WebBrowser 控件中显示现代内容时遇到了问题。要修复它,请查看this post
  • @MarkDiedericks 我在 GitHub 上为此示例创建了一个存储库,并添加了答案的链接。感谢您的反馈:)
  • @SunnyBhadana 我让它基于this post 工作。正如马克也提到的那样,不要为Edge 设置它,而是为IE 10 设置它。感谢您的反馈。
猜你喜欢
  • 2010-11-20
  • 1970-01-01
  • 2011-12-05
  • 2012-11-13
  • 1970-01-01
  • 2017-08-03
  • 1970-01-01
  • 2013-02-20
  • 1970-01-01
相关资源
最近更新 更多