WPF Web 浏览器控件中的 ckeditor

ckeditor in WPF WebBrowser Control

所以我在尝试 运行 wpf webbrowser 控件中的 ckeditor 时遇到了噩梦。我们公司在其网站上使用的自定义构建的 ckeditor 会抛出指向任何地方的错误.. 第 0 行,但它在其他任何地方都有效,包括 IE。基本包,半加载,但抛出未定义的错误并在加载阶段保持灰色。这是最新的 ck 编辑器 4.7。 我试过使用 3.6 版,但没有任何反应,ckeditor 没有抛出任何错误,但也没有加载(在 wpf 浏览器之外工作正常)。

这是我注入 wpfbrowser 的一些基本 html 代码。

            WebBrowser webBrowser = dependencyObject as WebBrowser;
        if (webBrowser != null)
        { 
            var html = "<head>" +

                       "<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />" +
                       "<meta charset=\"UTF-8\">" +

                      // $"<script type=\"text/javascript\" src=\"{ResourceDir}MathJax\MathJax.js?config=MML_HTMLorMML,default\"></script>" +
                       $"<script type=\"text/javascript\" src=\"{ResourceDir}ckeditor\ckeditor.js\"></script>" +
                       $"<script type=\"text/javascript\" src=\"{ResourceDir}JavaScript\essay.js\"></script>" +
                       // $"<link rel=\"stylesheet\" type=\"text/css\" href=\"{ResourceDir}\CSS\main.css\">" +

                       "</head>" +

                       "<body>" +
                       "         <form>\r\n" +
                       "            <textarea name=\"editor\" id=\"editor\" rows=\"10\" cols=\"80\">\r\n" +
                                    $"Hello World!" + /*{e.NewValue}*/
                       "            </textarea>\r\n" +
                       "        </form>"+
                       " <button onclick=\"ReplaceEditor()\">Click me</button> " +
                       "</body>";

            webBrowser.NavigateToString(html);

其他javascript如MathJax等都可以,请忽略我的构建方式HTML,现在不相关

这是essay.js内容

function ReplaceEditor() {
CKEDITOR.replace('editor');
}
window.onerror = function (message, url, lineNumber) {
    window.external.GetErrors(message, url, lineNumber);
}

捕获错误并没有太大帮助,因为它 returns 网络浏览器针对所有错误抛出的同一行 0 字符 0。感谢任何帮助,从我读过的内容来看,它应该像人们以前让它工作的那样工作。

我想我知道出了什么问题,您正在使用 NavigateToString,它会生成一个 about:blank 页面。这不适用于 CKEditor,与基于 file:// 的编辑器主机页面相同。你需要一个真正的基于 http/https 的页面,它可以像从他们的 CDN(一个非常可靠的亚马逊托管的)引用 CKEditor 一样简单:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>CKEditor</title>
        <script src="https://cdn.ckeditor.com/4.7.1/standard/ckeditor.js"></script>
    </head>
    <body>
        <textarea name="editor1"></textarea>
        <script>
            CKEDITOR.replace( 'editor1' );
        </script>
    </body>
</html>

下面是将 CKEditor Standard Editor Example 加载到 WPF WebBrowser 控件中的简单示例,它对我来说没有任何问题。

如果您不能拥有自己的专用在线页面来托管 CKEditor,您可能需要 运行 一个应用程序内单页 Web 服务器通过 http://localhost 为其提供服务。有很多关于如何做到这一点的例子(例如 this one)。

using Microsoft.Win32;
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;

namespace WpfWebEditor
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        WebBrowser _webBrowser;

        static MainWindow()
        {
            var fileName = System.IO.Path.GetFileName(Process.GetCurrentProcess().MainModule.FileName);
            SetBrowserFeatureControlKey("FEATURE_BROWSER_EMULATION", fileName, GetBrowserEmulationMode());
        }

        public MainWindow()
        {
            InitializeComponent();
            this.Loaded += MainWindow_Loaded;

            _webBrowser = new WebBrowser();
            this.Content = _webBrowser;
        }

        private void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            _webBrowser.Navigate("https://nightly.ckeditor.com/standard/samples/");
        }

        private static void SetBrowserFeatureControlKey(string feature, string appName, uint value)
        {
            using (var key = Registry.CurrentUser.CreateSubKey(
                String.Concat(@"Software\Microsoft\Internet Explorer\Main\FeatureControl\", feature),
                RegistryKeyPermissionCheck.ReadWriteSubTree))
            {
                key.SetValue(appName, (UInt32)value, RegistryValueKind.DWord);
            }
        }

        private static UInt32 GetBrowserEmulationMode()
        {
            int browserVersion = 7;
            using (var ieKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Internet Explorer",
                RegistryKeyPermissionCheck.ReadSubTree,
                System.Security.AccessControl.RegistryRights.QueryValues))
            {
                var version = ieKey.GetValue("svcVersion");
                if (null == version)
                {
                    version = ieKey.GetValue("Version");
                    if (null == version)
                        throw new ApplicationException("Microsoft Internet Explorer is required!");
                }
                int.TryParse(version.ToString().Split('.')[0], out browserVersion);
            }

            UInt32 mode = 11000; // Internet Explorer 11. Webpages containing standards-based !DOCTYPE directives are displayed in IE11 Standards mode. Default value for Internet Explorer 11.
            switch (browserVersion)
            {
                case 7:
                    mode = 7000; // Webpages containing standards-based !DOCTYPE directives are displayed in IE7 Standards mode. Default value for applications hosting the WebBrowser Control.
                    break;
                case 8:
                    mode = 8000; // Webpages containing standards-based !DOCTYPE directives are displayed in IE8 mode. Default value for Internet Explorer 8
                    break;
                case 9:
                    mode = 9000; // Internet Explorer 9. Webpages containing standards-based !DOCTYPE directives are displayed in IE9 mode. Default value for Internet Explorer 9.
                    break;
                case 10:
                    mode = 10000; // Internet Explorer 10. Webpages containing standards-based !DOCTYPE directives are displayed in IE10 mode. Default value for Internet Explorer 10.
                    break;
                default:
                    // use IE11 mode by default
                    break;
            }

            return mode;
        }
    }
}